A Quarkus REST service that solves and analyzes constraint optimization problems using WASM modules. This is the backend service for SolverForge.
- JDK 24 or above
- Maven
- Dynamic Class Generation: Generates Java domain classes and constraint providers at runtime from JSON specifications
- WASM Integration: Executes WebAssembly modules via Chicory compiler for high-performance constraint evaluation
- Full Constraint Streams API: Comprehensive support for constraint stream operations
- Score Analysis: Detailed constraint analysis through the
/analyzeendpoint
- WASM Module Caching: SHA-256 based caching prevents re-parsing identical WASM modules
- Export Function Caching: Cached WASM export lookups reduce overhead
- Predicate Result Caching: Memoization of predicate evaluation results
- Geometric List Growth: O(n) amortized append operations for efficient list handling
- Memory Layout Optimization: Aligned field offsets matching Rust's LayoutCalculator
Stream Transformations:
forEach- Iterate over planning entitiesforEachUniquePair- Process unique pairs with joinersjoin- Join streams with custom joinersfilter- Filter elements by predicatemap- Transform stream elementsexpand- One-to-many transformationsflattenLast- Flatten nested collections (including primitive int lists)ifExists/ifNotExists- Conditional existence checkscomplement- Set complement operations
Aggregations (via groupBy):
count- Count elementssum- Sum numeric valuesmin/max- Find minimum/maximum values (with null safety)average- Calculate averagesloadBalance- Fair load distribution aggregatorconsecutive- Consecutive sequence detectionconnectedRange- Connected range aggregation- Meta-aggregators:
compose,collectAndThen,conditional
Joiners:
- Equal, lessThan, lessThanOrEqual, greaterThan, greaterThanOrEqual joiners
- Overlapping and filtering joiners
- Primitives:
int,long,float,double - String and collections (including primitive int lists)
- Temporal types:
LocalDate,LocalDateTime - Score types:
SimpleScore,HardSoftScore,HardMediumSoftScore,HardSoftBigDecimalScore
- Auto-generated host functions for domain-specific operations
- String comparison:
hstringEquals - List operations:
hlistContainsString - Dynamic domain model parsing in host functions
- Health Endpoint: Service readiness checks via
/health - Solver Statistics: Response includes detailed metrics:
- Time spent (milliseconds)
- Score calculation count and speed
- Move evaluation count and speed
- Error Handling: Full cause chain with stack frames in error responses
A planning problem is structured as follows:
{
"domain": "DomainMap",
"constraints": "ConstraintMap",
"wasm": "Base64String",
"allocator": "ExportedWasmFunction (int) -> int",
"deallocator": "ExportedWasmFunction (int) -> void",
"solutionDeallocator": "Optional[ExportedWasmFunction (int) -> void]",
"listAccessor": "ListAccessor",
"termination": "Optional[TerminationConfig]",
"environmentMode": "Optional[EnvironmentMode]",
"problem": "String"
}{
"domain": {
"Employee": {
"fields": {"name": {"type": "String"}}
},
"Shift": {
"fields": {
"start": {"type": "int"},
"end": {"type": "int"},
"employee": {
"type": "Employee",
"accessor": {"getter": "getEmployee", "setter": "setEmployee"},
"annotations": [{"annotation": "PlanningVariable", "allowsUnassigned": true}]
}
}
},
"Schedule": {
"fields": {
"employees": {
"type": "Employee[]",
"accessor": {"getter": "getEmployees", "setter": "setEmployees"},
"annotations": [
{"annotation": "ProblemFactCollectionProperty"},
{"annotation": "ValueRangeProvider"}
]
},
"shifts": {
"type": "Shift[]",
"accessor": {"getter": "getShifts", "setter": "setShifts"},
"annotations": [
{"annotation": "PlanningEntityCollectionProperty"}
]
},
"score": {
"type": "SimpleScore",
"annotations": [{"annotation": "PlanningScore"}]
}
},
"mapper": {"fromString": "strToSchedule", "toString": "scheduleToStr"}
}
},
"constraints": {
"penalize unassigned": [
{"kind": "each", "className": "Shift"},
{"kind": "filter", "functionName": "unassigned"},
{"kind": "penalize", "weight": "1"}
]
},
"wasm": "...",
"allocator": "alloc",
"deallocator": "dealloc",
"listAccessor": {
"new": "newList",
"get": "getItem",
"set": "setItem",
"length": "size",
"append": "append",
"insert": "insert",
"remove": "remove"
},
"problem": "{\"employees\":[...], ...}",
"environmentMode": "FULL_ASSERT",
"termination": {"spentLimit": "1s"}
}Runs the solver and returns the optimized solution with statistics.
Response:
{
"solution": "{\"employees\":[...], ...}",
"score": "18",
"stats": {
"timeSpentMillis": 1234,
"scoreCalculationCount": 5678,
"scoreCalculationSpeed": 4567,
"moveEvaluationCount": 9012,
"moveEvaluationSpeed": 7345
}
}Returns constraint analysis for the provided solution.
Service readiness check for monitoring and orchestration.
mvn clean packagejava -jar target/solverforge-wasm-service-0.2.0-runner.jarThis project is derived from timefold-wasm-service by Christopher Chianelli, licensed under the Apache License 2.0.
This project uses Timefold Solver for constraint solving.
Apache License 2.0 - see LICENSE.txt