Dropwizard Bundle¶
mustang-dw-bundle wraps MustangEngine in a Dropwizard ConfiguredBundle, registering JAX-RS resources so you can expose Mustang's capabilities over HTTP without writing any glue code.
Dependency¶
<dependency>
<groupId>com.phonepe</groupId>
<artifactId>mustang-dw-bundle</artifactId>
<version>${mustang.version}</version>
</dependency>
Note: Find the latest version on Maven Central.
Registration¶
Extend MustangBundle and implement getMustangConfig:
import io.dropwizard.Application;
import io.dropwizard.Configuration;
import io.dropwizard.setup.Bootstrap;
import io.dropwizard.setup.Environment;
import com.phonepe.mustang.MustangBundle;
import com.phonepe.mustang.MustangConfig;
public class MyAppConfiguration extends Configuration {
private MustangConfig mustang;
public MustangConfig getMustang() { return mustang; }
}
public class MyApp extends Application<MyAppConfiguration> {
private final MustangBundle<MyAppConfiguration> mustangBundle =
new MustangBundle<>() {
@Override
public MustangConfig getMustangConfig(MyAppConfiguration config) {
return config.getMustang();
}
};
@Override
public void initialize(Bootstrap<MyAppConfiguration> bootstrap) {
bootstrap.addBundle(mustangBundle);
}
@Override
public void run(MyAppConfiguration config, Environment env) {
// Access the engine for your own use:
MustangEngine engine = mustangBundle.getMustangEngine();
// Index your criteria, set up reload schedules, etc.
}
}
config.yml:
mustang:
serviceName: my-service
MustangConfig fields¶
| Field | Type | Required | Description |
|---|---|---|---|
serviceName |
String |
Yes | Logical name of the service; used in metrics/logging |
Authentication¶
All endpoints require the JAX-RS role mustang_operator (constant MustangBundle.MUSTANG_PERMISSION). Wire this into your application's authentication/authorization mechanism (e.g., a @RolesAllowed filter).
REST API reference¶
All endpoints:
- Accept
Content-Type: application/json - Produce
application/json - Return
MustangResponse<T>wrapper:{ "success": true, "data": <T> } - On error:
{ "success": false, "errorCode": "<CODE>", "message": "..." }
POST /mustang/v1/search¶
Search the inverted index for all criteria matching an event.
Request body:
{
"indexName": "ads",
"requestContext": {
"node": { "country": "IN", "age": 25, "platform": "android" }
},
"score": false
}
| Field | Type | Required | Description |
|---|---|---|---|
indexName |
String |
Yes | Name of the index to search |
requestContext.node |
JsonNode |
Yes | The event as a JSON object |
score |
boolean |
No | Whether to compute relevance scores (default false) |
Response:
{
"success": true,
"data": ["segment-001", "segment-003"]
}
POST /mustang/v1/scan/index¶
Brute-force evaluate all criteria in the index against the event (slow; for validation).
Request body:
{
"indexName": "ads",
"requestContext": {
"node": { "country": "IN", "age": 25 }
}
}
Response: Same shape as search — Set<String> of matching IDs.
POST /mustang/v1/scan/criteria¶
Evaluate a provided list of criteria against the event (no index required).
Request body:
{
"criterias": [ { "form": "DNF", "id": "...", "conjunctions": [...] } ],
"requestContext": {
"node": { "country": "IN" }
}
}
Response: List<Criteria> — the matching criteria objects.
POST /mustang/v1/debug¶
Evaluate a single criteria against an event with per-predicate detail.
Request body:
{
"criteria": { "form": "DNF", "id": "rule-1", "conjunctions": [...] },
"requestContext": {
"node": { "country": "IN", "age": 25 }
}
}
Response:
{
"success": true,
"data": {
"id": "rule-1",
"form": "DNF",
"result": true,
"compositionDebugResults": [
{
"result": true,
"predicateDebugResults": [
{ "lhs": "$.country", "result": true },
{ "lhs": "$.age", "result": true }
]
}
]
}
}
POST /mustang/v1/index/export¶
Serialize a named index to a JSON string (for backup or migration).
Request body:
{ "indexName": "ads" }
Response: { "success": true, "data": "<json-string>" }
POST /mustang/v1/index/snapshot¶
Return a lightweight diagnostic view of an index's posting list structure.
Request body:
{ "indexName": "ads" }
Response: { "success": true, "data": "<snapshot-string>" }
POST /mustang/v1/index/ratify¶
Trigger or check ratification (anomaly detection) for an index.
Request body:
{
"indexName": "ads",
"fullFledged": true
}
Response:
{
"success": true,
"data": {
"status": true,
"timeTakenMs": 1234,
"combinations": { "totalCount": 500, "cpCount": 300, "ssCount": 200 },
"anamolyDetails": []
}
}
Metrics¶
All resource methods are annotated with @Timed and @ResponseMetered (Dropwizard Metrics). Metrics are exposed at the standard /metrics admin endpoint.
Exception mapping¶
MustangExceptionMapper is registered automatically. It maps MustangException error codes to HTTP status codes:
ErrorCode |
HTTP status |
|---|---|
INDEX_NOT_FOUND |
404 Not Found |
INDEX_GROUP_EXISTS |
409 Conflict |
| All others | 500 Internal Server Error |