SimulationService runs a REST API for running jobs in the ASKEM Model Representation.
The SimulationService follows the OpenAPI spec here
See example payloads in the ./examples
directory or at https://github.com/DARPA-ASKEM/simulation-api-spec.
using Revise # auto-update the server with your changes
using SimulationService
SimulationService.ENABLE_TDS[] = false # opt out of Terrarium Data Service
start!() # run server
# make code changes that you want to test...
start!() # Replaces the running server with your changes
docker compose --file docker/docker-compose.yml up --build
using SimulationService, HTTP, JSON3
# Start the server/job scheduler without Terrarium Data Service
SimulationService.ENABLE_TDS[] = false
start!()
url = SimulationService.server_url[] # server url
@info JSON3.read(HTTP.get(url).body) # Is server running? (status == "ok")
# JSON in ASKEM Model Representation
model = JSON3.read(read("./examples/BIOMD0000000955_askenet.json"))
# You can directly provide AMR JSON with the `model` key
json = (; model, timespan = (; start=0, var"end"=90), engine="sciml")
body = JSON3.write(json)
# Kick off the simulation job
res = HTTP.post("$url/simulate", ["Content-Type" => "application/json"]; body=body)
# Get the `id` so we can query the job status and get results
id = JSON3.read(res.body).simulation_id
# Re-run this until `status_obj.status == "done"`
status = JSON3.read(HTTP.get("$url/status/$id").body)
# close down server and scheduler
stop!()
The OpenAPI spec here is the source of truth. See the JSON files in ./examples
that begin with request-...
.
Here's a summary of what the JSON should like in a request:
- Every request should contain
"engine": "sciml"
- Endpoint-specific keys:
/simulate
- Required:
model_config_id
,timespan
- Optional:
extra
- Required:
/calibrate
- Required:
model_config_id
,dataset
- Optional:
extra
,timespan
- Required:
/ensemble
- Required:
model_config_ids
,timespan
- Optional:
extra
- Required:
Where (in Julia-speak):
model_config_id::String
model_config_ids::Vector{String}
timespan::JSON3.Object # keys (start::Number, end::Number)
extra::JSON3.Object # any keys possible
dataset::JSON3.Object # keys (id::String, filename::String, mappings::Object(col_name => new_col_name))
An incoming HTTP.Request
gets turned into a SimulationService.OperationRequest
object that holds
all the necessary info for running/solving the model and returning results.
- Request arrives
- We process the keys into useful things for
OperationRequest
model_config_id(s)
--> Retrieve model(s) in AMR format from TDS (model::JSON3.Object
inOperationRequest
).dataset
--> Retrieve dataset from TDS (df::DataFrame
inOperationRequest
).
- We start the job via JobSchedulers.jl, which performs:
- Update job status in TDS to "running".
- Run/solve the model/simulation.
- Upload results to S3.
- Update job status in TDS to "complete".
- Return a 201 response (above job runs async) with JSON that holds the
simulation_id
(client's term), which we callid
.
The Simulation Service (soon to be renamed SciML Service) is a REST API that wraps specific SciML tasks. The service should match the spec here since PyCIEMSS Service and SciML Service ideally are hot swappable.
The API creates a job using the JobSchedulers.jl library and updates the Terarium Data Service (TDS) with the status of the job throughout its execution. Once the job completes, the results are written to S3. With most of the output artifacts, we do little postprocessing after completing the SciML portion.