Resources

Optional registration unlocks capacity pools, resource trees, and blocker co-acquisition.

Registration is optional

You can reserve any string as a resource without registering it first — the simple case just works. Registration is only needed when you want:

Register resources

POST /api/v1/Resource/register
X-Api-Key: YOUR_API_KEY
Content-Type: application/json

[
  {
    "name":     "Printer",
    "capacity": 3,
    "blocks":   ["Ink"],
    "treePath": "Equipment>Office"
  }
]

Registration is idempotent — re-registering the same name overwrites the previous definition.

Registration fields

FieldTypeRequiredDescription
name string Yes Logical resource name. Must be unique within your tenant.
capacity integer No Number of physical slots. Default 1. Capacity > 1 auto-expands to Name_0, Name_1, … slots.
blocks string[] No Names of resources that must be co-acquired whenever this resource is reserved. All-or-nothing.
treePath string No Ancestor path using > as delimiter, e.g. "Company>Equipment>IT". Do not include the resource name itself. Ancestor nodes are auto-registered.

Capacity pools

Register a resource with capacity: N and reservations automatically claim the first available physical slot. Callers reserve the logical name ("Printer") and the server picks the slot ("Printer_0").

// Register: Printer with 3 slots → Printer_0, Printer_1, Printer_2
[{"name": "Printer", "capacity": 3}]

// Reserve the logical name — server assigns the slot
[{"requester": "print-job-7", "resource": "Printer"}]

// Response shows which slot was assigned
{
  "status": "ACQUIRED",
  "acquiredSlots": {"Printer": "Printer_0"}
}
Slot keys are immutable. Capacity slots are generated at register time from the capacity value. If you need to change capacity, re-register the definition — but be aware that in-flight reservations against old slots are not automatically migrated.

Blockers

A blocker is a resource that is automatically co-acquired whenever the parent resource is reserved. If any blocker is unavailable, the entire acquire fails.

// "Printer" always co-acquires "Ink" and "PrintQueue"
[{"name": "Printer", "blocks": ["Ink", "PrintQueue"]}]

// Reserve Printer — Ink and PrintQueue are acquired automatically
[{"requester": "job-1", "resource": "Printer"}]

// Response
{
  "status": "ACQUIRED",
  "acquiredBlockers": ["Ink", "PrintQueue"]
}

Blockers are held under a system requester, not the caller. They are only released when no requester holding the logical resource still needs them (smart release). Do not attempt to release blockers directly.

Resource trees

Resources can be placed in a hierarchy using treePath. Reserving a leaf resource automatically acquires all ancestor nodes (ALL_OR_NONE on the full chain). If any ancestor is at capacity, the entire acquire fails.

// Register two printers under a shared Equipment > IT node
[
  {"name": "Printer-A", "treePath": "Equipment>IT"},
  {"name": "Printer-B", "treePath": "Equipment>IT"}
]

// Reserving Printer-A also holds Equipment and IT
[{"requester": "job-1", "resource": "Printer-A"}]

// Response
{
  "status": "ACQUIRED",
  "reservedAtPath": "Equipment>IT>Printer-A"
}

List registered resources

GET /api/v1/Resource/definitions
X-Api-Key: YOUR_API_KEY
[
  {
    "name":     "Printer",
    "capacity": 3,
    "blocks":   ["Ink"],
    "treePath": "Equipment>Office"
  }
]

Check availability

GET /api/v1/Resource/available/{resource}
X-Api-Key: YOUR_API_KEY

Returns true if the resource has at least one free slot.

Get resource tree

GET /api/v1/Resource/tree
X-Api-Key: YOUR_API_KEY

Returns the full hierarchy with live capacity state — how many slots are available at each node.

Delete a resource

DELETE /api/v1/Resource/{name}?cascade=false
X-Api-Key: YOUR_API_KEY

Returns 400 if the resource has active reservations or has children (without cascade=true). Returns 404 if the name is not registered.

InMemory vs persistent modes

In InMemory mode (default, no database), resource definitions are held in memory and lost on restart. In Sqlite or Postgres mode, definitions are persisted to the database and reloaded into the resource manager on startup.