Skip to main content

API Flow - Summary

Last updated: August 18, 2026

L0 - Stage

L0 - Stage^api summary

Path from L0: Stage^api

Description: Entry point that stages a batch of records (assertions and/or retractions) into %ABR ahead of a later transactional commit by Transact^api. Resolves attribute keys, validates/stages each record via subroutine calls, and enforces all-or-nothing batch atomicity — the first failed record aborts and discards the entire staged batch.

  • Purpose
    • Take a multi-record input (Data), resolve each record’s attributes against the schema namespace ns, and stage the resulting datoms into %ABR so Transact^api can later commit them.
    • Guarantees atomicity at the batch level: any single record failure discards all staging done so far in this call.
  • Step 1 — Initial guard
    • Checks $DATA(%ABR); if not initialized, logs an error (LOGERROR^logger) stating %ABR wasn’t initialized and that INIT^api must be called first, sets ok=0, and quits immediately.
  • Step 2 — Setup / defaults
    • Declares working locals: idx, ReqAttr, AttrCache, recCount, failedIdx.
    • Defaults ns to "sandbox" if not supplied.
    • Defaults isBulkLoad to 0 (validation on) if not supplied.
    • Initializes recCount=0 and failedIdx="".
  • Step 3 — Build required-attributes map
    • BuildAttrsRequired^sapiBld — builds the required-attribute map for ns into ReqAttr, used later by record validation. Unexpanded; body not yet pasted.
  • Step 4 — Build attribute cache
    • BuildAttrsCache^sapiBld — builds the forward/reverse attribute-key cache for ns into AttrCache; forward map is used for attribute resolution, reverse map for validation. Unexpanded; body not yet pasted.
  • Step 5 — Main per-record loop
    • Iterates idx=$ORDER(Data(idx)) over all top-level record indices in Data.
    • Loop exits when idx is exhausted or as soon as ok<1 (first failure) — remaining records are never attempted.
    • For each idx:
      • NEW ResolvedRec; increments recCount.
      • ResolveRecAttrs^apiRslv — resolves the record’s attribute keys (from Data(idx,...)) to internal aids using AttrCache, returning ok and populating ResolvedRec. Unexpanded; body not yet pasted.
      • If resolution fails (ok=0): sets failedIdx=idx, logs an error that attribute resolution failed and the batch will be aborted, then exits the inner DO block (loop condition then breaks the FOR).
      • Otherwise, calls StageRecord^apiWFL — validates (unless isBulkLoad) and stages the resolved record’s attributes into %ABR, returning ok. Unexpanded; body not yet pasted.
      • If ok<1 after staging, sets failedIdx=idx.
  • Step 6 — Post-loop outcome handling
    • If ok<1 (some record failed): kills %ABR, resets SET %ABR=0, and logs an error summarizing the abort — which idx failed, the ok value, how many records were attempted, and ns. Entire batch is discarded, not just the failing record.
    • Else if %ABR (defaulted via $GET(%ABR,0)) is 0: sets ok=2 and logs an info line noting a no-op — nothing was staged/committed.
    • Else (normal success): logs an info line summarizing records attempted, records staged (%ABR count), ns, and isBulkLoad.
    • Logging in this step and throughout uses LOGERROR^logger / LOGINFO^logger as inline logging utility calls — not treated as a distinct business-logic level to drill into.
  • Step 7 — Quit
    • Returns control to caller with ok set per the outcome above.

L0 - Stage^api diagram

flowchart TD
    Start(["Start: 'Stage^api'"]) --> CheckInit{"Is '%ABR' initialized?"}
    
    CheckInit -->|"No"| LogInitErr["Log error:<br/>'%ABR' not initialized"]
    LogInitErr --> ReturnFail0(["Return ok = 0"])
    
    CheckInit -->|"Yes"| SetDefaults["Set defaults for<br/>namespace and bulk-load flag;<br/>initialize counters"]
    
    SetDefaults --> BuildReq["'BuildAttrsRequired^sapiBld'<br/>build required-attributes map<br/>(internals not yet verified)"]
    
    BuildReq --> BuildCache["'BuildAttrsCache^sapiBld'<br/>build forward/reverse<br/>attribute cache<br/>(internals not yet verified)"]
    
    BuildCache --> LoopStart{"More records<br/>remaining in input?"}
    
    LoopStart -->|"No"| PostLoop
    LoopStart -->|"Yes, and no prior failure"| ResolveAttrs["'ResolveRecAttrs^apiRslv'<br/>resolve record's attribute<br/>keys to internal aids<br/>(internals not yet verified)"]
    
    ResolveAttrs --> ResolveOk{"Resolution<br/>succeeded?"}
    
    ResolveOk -->|"No"| LogResolveErr["Log error:<br/>attribute resolution failed;<br/>record failing index"]
    LogResolveErr --> LoopStart
    
    ResolveOk -->|"Yes"| StageRec["'StageRecord^apiWFL'<br/>validate (unless bulk load)<br/>and stage record into '%ABR'<br/>(internals not yet verified)"]
    
    StageRec --> StageOk{"Staging<br/>succeeded?"}
    
    StageOk -->|"No"| MarkFailed["Mark record<br/>as failed index"]
    MarkFailed --> LoopStart
    
    StageOk -->|"Yes"| LoopStart
    
    PostLoop{"Did any record<br/>fail during batch?"}
    
    PostLoop -->|"Yes"| Rollback["Discard entire batch:<br/>kill and reset '%ABR'"]
    Rollback --> LogAbort["Log error:<br/>batch aborted at failing index;<br/>records attempted count"]
    LogAbort --> ReturnFailBatch(["Return ok < 1"])
    
    PostLoop -->|"No"| CheckNoop{"Were any records<br/>actually staged?"}
    
    CheckNoop -->|"No, zero staged"| LogNoop["Log info:<br/>no-op, nothing staged"]
    LogNoop --> ReturnNoop(["Return ok = 2"])
    
    CheckNoop -->|"Yes, one or more staged"| LogSuccess["Log info:<br/>records attempted and<br/>records staged summary"]
    LogSuccess --> ReturnSuccess(["Return ok = 1"])

L1 - ResolveRecAttrs

L1 - ResolveRecAttrs^apiRslv summary

Path from L0: Stage^api → Step 5 → ResolveRecAttrs^apiRslv

Description: Resolves a single record’s attribute names (from Data(idx,...)) into internal attribute IDs, building ResolvedRec(op,aid)=value for both assertions ("+") and retractions ("-"). Called once per record inside Stage^api’s main loop (Step 5). Fails fast on the first unresolvable attribute.

  • Purpose

    • Translate a record’s human-readable attribute names (e.g. movie.title) into internal attribute IDs (aids), using the namespace ns and the pre-built AttrCache.
    • Separate assertion values (ResolvedRec("+",aid)=value) from retraction values (ResolvedRec("-",aid)=value) so downstream staging knows which operation applies to each attribute.
  • Step 1 — Setup

    • Declares locals akey, aid, ok.
    • Initializes akey="" and ok=1.
  • Step 2 — Per-attribute resolution loop

    • Iterates akey=$ORDER(@dataRef@(akey)) over all attribute-name subscripts of the record referenced by dataRef.
    • Loop exits when akey is exhausted or as soon as ok=0 (first unresolvable attribute) — remaining attributes are never attempted.
    • For each akey:
      • Calls ResolveAttr^apiRslv — resolves a single attribute name to its internal aid, trying the namespace-prefixed key first, then a bare key. Unexpanded above this point but shown below (L2).
      • If aid=0 (unresolvable): sets ok=0 and exits the inner DO block, which breaks the FOR loop on the next iteration check.
      • Otherwise:
        • If the record has a direct (non-retraction) value at @dataRef@(akey) — checked via $DATA(...)#10 (data-value-present bit) — stores it as an assertion: ResolvedRec("+",aid)=value.
        • If the record also has a retraction sub-node at @dataRef@(akey,"-"), stores it as a retraction: ResolvedRec("-",aid)=value. This means a single attribute key can yield both an assertion and a retraction entry if both forms are present in the input.
  • Step 3 — Quit

    • Returns ok (1 if every attribute resolved, 0 if any attribute could not be resolved) to the caller (Stage^api, Step 5).

L2 - ResolveAttr^apiRslv

Path from L0: Stage^api → Step 5 → ResolveRecAttrs^apiRslv → Step 2 → ResolveAttr^apiRslv

Description: Resolves a single attribute name string to its internal attribute ID, first trying it as a namespace-prefixed key, then falling back to a bare (unprefixed) key. Returns 0 if neither lookup succeeds. This is a leaf routine — no further calls deeper than this.

  • Purpose

    • Given one attribute name (akey) and the current namespace (ns), look up the corresponding internal aid in AttrCache, supporting both namespace-scoped attributes and global/bare-keyed attributes (e.g. system attributes like sys.attr.id).
  • Step 1 — Try namespace-prefixed lookup

    • Builds the key ns_"."_akey (e.g. sandbox.movie.genre) and looks it up in AttrCache, coercing the result to a number via unary + (so a missing/non-numeric entry becomes 0).
  • Step 2 — Fallback to bare-key lookup

    • If the prefixed lookup returned 0, tries AttrCache(akey) directly (e.g. sys.attr.id), again coerced to a number via unary +.
  • Step 3 — Failure logging

    • If both lookups returned 0 (attribute unresolvable by either method), logs an error (LOGERROR^logger) naming the unresolvable attribute, the ns, and noting that record resolution is being aborted. Logging is an inline utility call, not treated as a deeper level.
  • Step 4 — Quit

    • Returns aid — either a resolved internal attribute ID (>0) or 0 if unresolvable — to the caller (ResolveRecAttrs^apiRslv, Step 2).

L1 - ResolveRecAttrs^apiRslv flowchart

flowchart TD
    R1Start(["'ResolveRecAttrs^apiRslv' — Step 1:<br/>Setup locals"]) --> R2Loop{"'ResolveRecAttrs^apiRslv' — Step 2:<br/>More attribute keys<br/>remaining in record?"}

    R2Loop -->|"No"| R3Return(["'ResolveRecAttrs^apiRslv' — Step 3:<br/>Return ok to Stage^api"])

    R2Loop -->|"Yes, and no prior failure"| CallResolveAttr["'ResolveAttr^apiRslv'<br/>resolve one attribute name<br/>to internal aid"]

    CallResolveAttr --> RA1["'ResolveAttr^apiRslv' — Step 1:<br/>Try namespace-prefixed<br/>key lookup"]

    RA1 --> RA1Check{"Prefixed lookup<br/>resolved?"}

    RA1Check -->|"Yes"| RA4Return(["'ResolveAttr^apiRslv' — Step 4:<br/>Return resolved aid"])

    RA1Check -->|"No"| RA2["'ResolveAttr^apiRslv' — Step 2:<br/>Try bare-key<br/>fallback lookup"]

    RA2 --> RA2Check{"Bare-key lookup<br/>resolved?"}

    RA2Check -->|"Yes"| RA4Return

    RA2Check -->|"No"| RA3["'ResolveAttr^apiRslv' — Step 3:<br/>Log error —<br/>attribute unresolvable"]

    RA3 --> RA4ReturnZero(["'ResolveAttr^apiRslv' — Step 4:<br/>Return aid = 0"])

    RA4Return --> R2AfterCall{"'ResolveRecAttrs^apiRslv' — Step 2:<br/>Was aid resolved<br/>(non-zero)?"}
    RA4ReturnZero --> R2AfterCall

    R2AfterCall -->|"No, aid = 0"| R2SetFail["Set failure flag,<br/>stop processing<br/>remaining attributes"]
    R2SetFail --> R3Return

    R2AfterCall -->|"Yes"| R2StoreCheck{"Does key have a<br/>direct assertion value?"}

    R2StoreCheck -->|"Yes"| R2StoreAssert["Store as assertion in<br/>ResolvedRec plus-branch,<br/>keyed by aid, value"]
    R2StoreCheck -->|"No"| R2CheckRetract

    R2StoreAssert --> R2CheckRetract{"Does key also have<br/>a retraction sub-node?"}

    R2CheckRetract -->|"Yes"| R2StoreRetract["Store as retraction in<br/>ResolvedRec minus-branch,<br/>keyed by aid, value"]
    R2CheckRetract -->|"No"| R2Loop

    R2StoreRetract --> R2Loop

L1 - StageRecord

L1 - StageRecord^apiWFL summary

Path from L0: Stage^api → Step 5 → StageRecord^apiWFL

Description: Resolves the target entity for a record, validates its facts (unless bulk load), then stages the record’s assertions and retractions as datoms into %ABR. Assertions are processed before retractions so the entity key is staged first. Wraps the staging phase in $ETRAP to contain runtime errors without aborting Stage^api’s outer loop. Called once per record inside Stage^api’s main loop (Step 5), after ResolveRecAttrs^apiRslv succeeds.

  • Purpose
    • Take one record’s already-resolved attributes (ResolvedRec), determine/resolve its target entity, validate the record’s facts, and write the resulting assertion/retraction datoms into %ABR.
    • Distinguish four outcomes for the caller: no-op (2), staged cleanly (1), controlled failure (0), or uncaught runtime error (-1).
  • Step 1 — Setup
    • Declares locals eid, isNewEntity, hasChanges, result.
    • Initializes eid=0, result=1, hasChanges=0.
  • Step 2 — Resolve target entity
    • Calls ResolveTargetEntity^apiRslv — resolves/derives the target entity ID from ResolvedRec, mutating ResolvedRec in the process (control attributes are consumed here); success/error logging happens inside it. Unexpanded; body not yet pasted.
    • If eid=0 (resolution failed), quits immediately with 0. No transaction is open yet, so this is a direct abort — no rollback needed.
  • Step 3 — Validate entity facts
    • Calls IsEntityRegistered^apiVld — checks whether eid is a previously registered entity; result is inverted and stored as isNewEntity. Unexpanded; body not yet pasted.
    • If isBulkLoad is false:
      • Calls ValidateRecord^apiVld — validates the record’s facts against ReqAttr and AttrCache, given whether the entity is new; returns result. Unexpanded; body not yet pasted.
    • Else (isBulkLoad true):
      • Skips validation entirely and logs a warning (LOGWARNING^logger) noting required-attribute checks were bypassed for this eid.
    • If result is falsy after this: logs an error that entity fact validation failed, and quits with 0. Still no transaction open — direct abort.
  • Step 4 — Stage datoms into %ABR
    • Arms NEW $ETRAP set to GOTO StageRecordERR^apiWFL, scoping error trapping to this phase only, so an uncaught runtime error here doesn’t propagate up and abort Stage^api’s per-record loop uncontrolled — it’s caught locally instead.
    • Declares aid (current attribute id being walked) and ok (per-attribute staging outcome; only a 0 stops a loop early).
    • Sets ok=1.
    • Assertions first: iterates aid=$ORDER(ResolvedRec("+",aid)), calling DatomAssert (local function, same call depth — inline helper) for each, which returns 1 (staged), 2 (no-op), or 0 (failed) per attribute. Loop stops early only when ok becomes 0.
    • Retractions second, only if assertions succeeded: if ok is still truthy, iterates aid=$ORDER(ResolvedRec("-",aid)), calling DatomRetract (local function, same call depth — inline helper) for each, same return convention. Loop stops early only when ok becomes 0.
    • This ordering (assertions before retractions) guarantees the entity key is staged before any retraction is attempted against it.
  • Step 5 — Determine final result
    • Sets hasChanges from $DATA(%ABR(eid))>0 — this is what actually distinguishes “wrote something” from “processed cleanly but nothing changed”; the per-attribute 1-vs-2 outcomes from DatomAssert/DatomRetract aren’t separately tracked.
    • If ok=0: sets result=0 (controlled failure — some attribute staging failed).
    • Else if hasChanges: sets result=1 (staged cleanly, something changed).
    • Else: sets result=2 (no-op — processed cleanly but nothing changed).
  • Step 6 — End
    • GOTO StageRecordEND — jumps to the routine’s end label (not shown yet) to return result to the caller. This is a same-routine control-flow jump, not a deeper call, so it stays inline rather than becoming its own level.
    • (Implicit, not yet shown: StageRecordERR^apiWFL is the $ETRAP target for Step 4’s runtime-error path, which presumably sets result=-1 before falling through to the same end point — body not yet pasted.)

L1 - StageRecord^apiWFL flowchart

flowchart TD
    S1Start(["'StageRecord^apiWFL' — Step 1:<br/>Setup locals"]) --> S2Resolve["'ResolveTargetEntity^apiRslv'<br/>resolve target entity id<br/>(internals not yet verified)"]

    S2Resolve --> S2Check{"'StageRecord^apiWFL' — Step 2:<br/>Entity resolved?"}

    S2Check -->|"No, eid = 0"| S2ReturnFail(["Return result = 0<br/>(no transaction open,<br/>direct abort)"])

    S2Check -->|"Yes"| S3Registered["'IsEntityRegistered^apiVld'<br/>check if entity already<br/>registered<br/>(internals not yet verified)"]

    S3Registered --> S3BulkCheck{"'StageRecord^apiWFL' — Step 3:<br/>Is this a bulk load?"}

    S3BulkCheck -->|"No"| S3Validate["'ValidateRecord^apiVld'<br/>validate record's facts<br/>against required attrs<br/>(internals not yet verified)"]

    S3BulkCheck -->|"Yes"| S3LogWarn["Log warning:<br/>validation skipped,<br/>required-attr checks bypassed"]

    S3Validate --> S3ResultCheck{"'StageRecord^apiWFL' — Step 3:<br/>Validation succeeded?"}

    S3ResultCheck -->|"No"| S3LogErr["Log error:<br/>entity fact validation failed"]
    S3LogErr --> S3ReturnFail(["Return result = 0<br/>(no transaction open,<br/>direct abort)"])

    S3ResultCheck -->|"Yes"| S4Arm
    S3LogWarn --> S4Arm

    S4Arm["'StageRecord^apiWFL' — Step 4:<br/>Arm ETRAP scoped to<br/>this staging phase"] --> S4AssertLoop{"More assertion<br/>attributes remaining?"}

    S4AssertLoop -->|"Yes, and no prior failure"| S4DatomAssert["DatomAssert<br/>stage one asserted<br/>attribute value"]

    S4DatomAssert --> S4AssertOkCheck{"Attribute staged<br/>(not failed)?"}

    S4AssertOkCheck -->|"Yes"| S4AssertLoop
    S4AssertOkCheck -->|"No"| S5Determine

    S4AssertLoop -->|"No more assertions"| S4RetractGate{"Did all assertions<br/>succeed?"}

    S4RetractGate -->|"No"| S5Determine
    S4RetractGate -->|"Yes"| S4RetractLoop{"More retraction<br/>attributes remaining?"}

    S4RetractLoop -->|"Yes, and no prior failure"| S4DatomRetract["DatomRetract<br/>stage one retracted<br/>attribute value"]

    S4DatomRetract --> S4RetractOkCheck{"Attribute staged<br/>(not failed)?"}

    S4RetractOkCheck -->|"Yes"| S4RetractLoop
    S4RetractOkCheck -->|"No"| S5Determine

    S4RetractLoop -->|"No more retractions"| S5Determine

    S5Determine{"'StageRecord^apiWFL' — Step 5:<br/>Did any attribute<br/>staging fail?"}

    S5Determine -->|"Yes"| S5ResultFail(["Set result = 0<br/>controlled failure"])

    S5Determine -->|"No"| S5ChangesCheck{"Did staging produce<br/>an actual change<br/>to percent-ABR?"}

    S5ChangesCheck -->|"Yes"| S5ResultChanged(["Set result = 1<br/>staged cleanly"])
    S5ChangesCheck -->|"No"| S5ResultNoop(["Set result = 2<br/>no-op, nothing changed"])

    S5ResultFail --> S6End(["'StageRecord^apiWFL' — Step 6:<br/>GOTO end label,<br/>return result to Stage^api"])
    S5ResultChanged --> S6End
    S5ResultNoop --> S6End

    S2ReturnFail -.->|"returns to<br/>Stage^api Step 5"| Done(["Back to caller"])
    S3ReturnFail -.->|"returns to<br/>Stage^api Step 5"| Done
    S6End -.->|"returns to<br/>Stage^api Step 5"| Done

    ETrapNote["Note: uncaught runtime error<br/>during Step 4 jumps to<br/>StageRecordERR^apiWFL<br/>(internals not yet verified,<br/>presumably sets result = -1)"]

L2 - ResolveTargetEntity^apiRslv summary

Path from L0: Stage^api → Step 5 → StageRecord^apiWFL → Step 2 → ResolveTargetEntity^apiRslv

Description: Dispatches to one of three entity-resolution strategies based on which control attribute is present in the resolved record (sys.attr.id, sys.attr.key, or neither), returning the resolved/generated entity ID or 0 on failure.

  • Purpose
    • Determine the target entity that the record’s assertions/retractions apply to, using a strict priority order of control attributes, and mutate ResolvedRec to consume those control attributes so they don’t leak through as ordinary entity facts.
  • Step 1 — Setup
    • Declares eid; initializes eid=0.
  • Step 2 — Path dispatch (mutually exclusive, priority order)
    • Path 0 — explicit raw EID: if ResolvedRec("+",SYSATTRID) exists, calls ResolveByEID^apiRslv — resolves the entity via an explicit raw EID value. Unexpanded above; drilled into below (L3).
    • Path 1 — natural key: else if ResolvedRec("+",AKEYID) exists, calls ResolveByNaturalKey^apiRslv — find-or-create resolution via sys.attr.key. Drilled into below (L3).
    • Path 2 — unique-attribute resolution: else (neither control attribute present), calls ResolveByUnique^apiRslv — find-or-create resolution via a uniquely-constrained attribute, optionally disambiguated by sys.attr.resolvedby. Drilled into below (L3).
  • Step 3 — Quit
    • Returns eid (resolved entity ID, or 0 on any path’s failure) to the caller (StageRecord^apiWFL, Step 2).
L3 - ResolveByEID^apiRslv

Path from L0: … → ResolveTargetEntity^apiRslv → Path 0 → ResolveByEID^apiRslv

Description: Resolves the target entity using an explicit raw EID value supplied via sys.attr.id, after removing that control attribute from ResolvedRec so it doesn’t reach staging as an entity fact.

  • Purpose
    • Trust the caller-supplied raw entity ID, but only after validating both its structural shape and its existence, delegating that work to GetEID^apiGet.
  • Step 1 — Read and consume control attribute
    • Reads idval from ResolvedRec("+",SYSATTRID).
    • Kills ResolvedRec("+",SYSATTRID) immediately — this node must not reach DatomAssert as an entity fact.
  • Step 2 — Resolve via GetEID
    • Calls GetEID^apiGet — validates both the format (structurally valid EID) and existence (must exist) of idval; logs both success and failure internally. Drilled into below (L4).
  • Step 3 — Quit
    • Returns eid (resolved ID or 0) to the caller (ResolveTargetEntity^apiRslv, Path 0).
L4 - GetEID^apiGet

Path from L0: … → ResolveByEID^apiRslv → Step 2 → GetEID^apiGet (Note: also reachable from ResolveByNaturalKey^apiRslv at L4 via a different call path — see below.)

Description: General-purpose entity-reference resolver supporting three resolution paths (strict EID, sys.attr.key, or unique-attribute lookup), tried in order depending on which arguments are supplied. Used by both ResolveByEID^apiRslv (path 0 only, no aid) and ResolveByNaturalKey^apiRslv (paths 0–1, no aid).

  • Purpose

    • Resolve any supported entity reference (val) to an internal entity ID, trying strict EID validation first, then sys.attr.key lookup, then (if an aid is supplied) unique-attribute lookup.
  • Step 1 — Guard: empty value

    • If val="", logs an error and quits 0 immediately — fails fast before touching any globals.
  • Step 2 — Setup and guard: aid shape

    • Declares eid, isEidShaped; initializes eid=0.
    • Defaults aid via $GET(aid).
    • If aid is supplied but not numeric, logs an error (must be numeric; directs caller to LookupEID^api for sys.attr.key string resolution) and quits 0.
  • Step 3 — Path 0: strict EID validation + existence check

    • Calls IsEID^utils — performs structural validation of val as an EID shape. Unexpanded; body not yet pasted.
    • If val is EID-shaped:
      • Calls IsEntityRegistered^apiVld — checks whether the raw EID val is registered/exists. Unexpanded; body not yet pasted (also referenced earlier at L1/StageRecord Step 3, not yet drilled into).
      • If registered: sets eid=val, logs debug (resolved via EID).
      • Else: logs debug (valid EID shape but not registered) — eid stays 0.
      • Quits immediately after this branch, regardless of outcome — Paths 1 and 2 are unreachable once val is EID-shaped.
  • Step 4 — Path 1: sys.attr.key lookup (only if aid omitted, and val not EID-shaped)

    • If aid="":
      • Calls ResolveLiveEID^apiRslv with AKEYID and val — resolves the live entity currently claiming this sys.attr.key value. Unexpanded; body not yet pasted (referenced but not shown in this batch).
      • Logs debug either way (resolved or not resolvable via sys.attr.key).
      • Quits with eid from this path.
  • Step 5 — Path 2: unique-attribute lookup (only reached if aid was supplied)

    • Calls ResolveLiveEID^apiRslv with aid and val. Unexpanded; same subroutine as Step 4, different arguments.
    • Logs debug either way (resolved or not resolvable via aid/val).
  • Step 6 — Quit

    • Returns eid to the caller.
    • Liveness note (from header comment): both Path 1 and Path 2 walk all candidate eids under ^AVET(aid,valkey,candidate) and accept only the one whose most recent transaction for aid is still asserting exactly valkey — i.e., ResolveLiveEID^apiRslv filters out stale/dead claimants rather than taking the first $ORDER hit.
L3 - ResolveByNaturalKey^apiRslv

Path from L0: … → ResolveTargetEntity^apiRslv → Path 1 → ResolveByNaturalKey^apiRslv

Description: Find-or-create resolution via the sys.attr.key control attribute — returns the existing entity if the key is already registered, otherwise generates and returns a brand-new entity ID. Unlike ResolveByEID, this control attribute is not removed from ResolvedRec (it must reach DatomAssert as an entity fact, anchoring the entity to this key going forward).

  • Purpose
    • Implement find-or-create semantics for natural-key-based entity resolution; this path never fails.
  • Step 1 — Read control attribute
    • Reads keyval from ResolvedRec("+",AKEYID). Note: not killed here (comment explicitly says it must reach DatomAssert as an entity fact).
  • Step 2 — Attempt resolution
    • Calls GetEID^apiGet with keyval (no aid — so only Paths 0/1 inside GetEID are reachable; Path 0 is a no-op since a natural key value won’t be EID-shaped in practice, so this effectively resolves via Path 1). Same subroutine as drilled into above (L4).
  • Step 3 — Find-or-create branch
    • If eid>0: logs debug (resolved via sys.attr.key).
    • Else: calls GENID^utils — generates a new time-sorted compact entity ID. Drilled into below (L4). Logs debug (new entity generated).
  • Step 4 — Quit
    • Returns eid (always >0 — find-or-create never fails) to the caller (ResolveTargetEntity^apiRslv, Path 1).
L4 - GENID^utils

Path from L0: … → ResolveByNaturalKey^apiRslv → Step 3 → GENID^utils (Also called from ResolveByUnique^apiRslv and ResolveOwnership^apiRslv at other depths — see below.)

Description: Leaf utility that generates a KSUID-style time-sorted compact ID: a 13-character hex timestamp prefix (via $$EPOCH) followed by a random Base36 suffix of configurable length (default 7).

  • Purpose
    • Produce a chronologically sortable, effectively-unique identifier for newly created entities.
  • Step 1 — Setup
    • Declares CHARSET, RAND, I, POS.
    • Defaults RLEN to 7 via $GET(RLEN,7).
    • Sets CHARSET to the Base36 alphabet (0-9, a-z).
    • Initializes RAND="".
  • Step 2 — Generate random suffix
    • Loops I=1:1:RLEN, each iteration picking a random character from CHARSET via $RANDOM and appending it to RAND.
  • Step 3 — Quit
    • Returns $$EPOCH_RAND — concatenation of the epoch-derived hex timestamp (from EPOCH, an unexpanded same-routine-or-namespace function per the header comment — not yet pasted) and the random suffix.
L3 - ResolveByUnique^apiRslv

Path from L0: … → ResolveTargetEntity^apiRslv → Path 2 → ResolveByUnique^apiRslv

Description: Find-or-create resolution via a uniquely-constrained attribute. Dispatches across four sub-cases based on how many unique attributes are present in the record and whether sys.attr.resolvedby was supplied to disambiguate.

  • Purpose

    • Handle entity resolution when the record carries no explicit EID or natural key, instead relying on schema-declared unique attributes (with sys.attr.resolvedby required when more than one is present).
  • Step 1 — Setup

    • Declares count, firstAid, eid; initializes eid=0.
  • Step 2 — Count unique attributes

    • Calls CountUniqueAttributes^apiRslv — single pass over ResolvedRec’s assertions, counting how many carry a uniqueness constraint and capturing the first one’s aid. Drilled into below (L4).
  • Step 3 — Case: resolvedby present but no unique attributes

    • If count=0 and ResolvedRec("+",RESOLVEDBYID) exists: logs an error (resolvedby specified but no unique attributes supplied) and quits 0.
  • Step 4 — Case: no unique attributes, no resolvedby (anonymous entity)

    • If count=0 (and resolvedby absent, per Step 3 having already handled the other case): calls GENID^utils to mint a new entity, logs a warning (not debug — anonymous entity creation is flagged more prominently), and quits with that eid.
  • Step 5 — Case: exactly one unique attribute

    • If count=1: quits directly with the result of calling ResolveOwnership^apiRslv(firstAid,.ResolvedRec) — passes firstAid straight through. Drilled into below (L5, under ResolveDesignatedUnique) — note: this is the same subroutine reached one level shallower here than via the multi-attribute path below (see Open Items).
  • Step 6 — Case: multiple unique attributes, resolvedby required

    • If count>1… (implicitly — this line is reached only when count is neither 0 nor 1): if ResolvedRec("+",RESOLVEDBYID) is absent, logs an error (multiple unique attributes require sys.attr.resolvedby) and quits 0.
    • Otherwise, calls ResolveDesignatedUnique^apiRslv — validates and resolves via the caller-designated unique attribute. Drilled into below (L4).
    • Kills ResolvedRec("+",RESOLVEDBYID) if present — this control attribute must not reach DatomAssert as an entity fact.
  • Step 7 — Quit

    • Returns eid to the caller (ResolveTargetEntity^apiRslv, Path 2).
L4 - CountUniqueAttributes^apiRslv

Path from L0: … → ResolveByUnique^apiRslv → Step 2 → CountUniqueAttributes^apiRslv

Description: Pure counting pass over ResolvedRec’s assertions — determines how many carry a uniqueness constraint and returns the first one found. Does no resolution, lookup, staging, or validation itself; exists solely to inform ResolveByUnique’s dispatch.

  • Purpose
    • Single-pass scan to count unique-constrained assertion attributes and capture the first one’s aid, for use in ResolveByUnique^apiRslv’s branching.
  • Step 1 — Setup
    • Declares aid; initializes count=0, firstAid="".
  • Step 2 — Scan loop
    • Iterates aid=$ORDER(ResolvedRec("+",aid)) over all assertion attributes.
    • For each: calls GetUniqueMode^sapiGet — returns the attribute’s uniqueness constraint mode (or 0 if none). Drilled into below (L5).
      • If truthy (attribute is unique): increments count; if firstAid="", sets firstAid=aid.
  • Step 3 — Return (procedure, no explicit value)
    • QUIT with no value — count and firstAid are returned via pass-by-reference OUT parameters.
L5 - GetUniqueMode^sapiGet

Path from L0: … → CountUniqueAttributes^apiRslv → Step 2 → GetUniqueMode^sapiGet (Also called directly from ResolveDesignatedUnique^apiRslv — see below.)

Description: Leaf schema lookup that returns an attribute’s uniqueness constraint mode as a schema enumeration EID (UNQINSERTID, UNQUPSERTID, or 0 for none), replacing an older pair of boolean-returning functions.

  • Purpose
    • Given an attribute ID, report whether — and how — it enforces uniqueness, so callers can compare against schema EIDs directly.
  • Step 1 — Check insert-unique
    • If ^TBAVET(UNIQUEID,INSERTKEY,aid) exists (double-negated $DATA check), quits UNQINSERTID.
  • Step 2 — Check upsert-unique
    • Else if ^TBAVET(UNIQUEID,UPSERTKEY,aid) exists, quits UNQUPSERTID.
  • Step 3 — No constraint
    • Else quits 0.
L4 - ResolveDesignatedUnique^apiRslv

Path from L0: … → ResolveByUnique^apiRslv → Step 6 → ResolveDesignatedUnique^apiRslv

Description: Resolves the target entity when multiple unique attributes are present and the caller has designated which one to use via sys.attr.resolvedby. Runs four sequential validations before delegating to ResolveOwnership^apiRslv; any single failure aborts with 0.

  • Purpose
    • Ensure the caller-designated attribute is schema-valid, actually unique, present in the record, and non-empty, before applying ownership semantics to it.
  • Step 1 — Setup
    • Declares attrkey, aid, val, eid; initializes eid=0.
    • Reads attrkey from ResolvedRec("+",RESOLVEDBYID).
  • Step 2 — Validation 1: schema existence
    • Calls GetEID^sapiGet (note: sapiGet, distinct from apiGet’s GetEID drilled into at L4 above — unexpanded; body not yet pasted) with attrkey to resolve aid.
    • If aid<1: logs an error (resolvedby attribute not registered in schema) and quits 0.
  • Step 3 — Validation 2: attribute is unique
    • Calls GetUniqueMode^sapiGet (same subroutine drilled into above, L5) with aid.
    • If falsy: logs an error (resolvedby attribute is not unique) and quits 0.
  • Step 4 — Validation 3: attribute present in record
    • If ResolvedRec("+",aid) doesn’t exist: logs an error (resolvedby attribute missing from record) and quits 0.
  • Step 5 — Validation 4: value non-empty
    • Reads val via $GET(ResolvedRec("+",aid)).
    • If val="": logs an error (resolvedby attribute has empty value) and quits 0.
  • Step 6 — Delegate
    • If all four validations pass, quits directly with the result of calling ResolveOwnership^apiRslv(aid,.ResolvedRec). Drilled into below (L5).
L5 - ResolveOwnership^apiRslv

Path from L0: … → ResolveDesignatedUnique^apiRslv → Step 6 → ResolveOwnership^apiRslv (Also reachable directly from ResolveByUnique^apiRslv — Step 5 above — at one call-depth shallower, i.e. L4 via that path; see Open Items.)

Description: Resolves (or generates) the entity ID for a single unique attribute by applying UNQINSERT/UNQUPSERT ownership semantics, distinguishing “live” claimants from stale/dead ones so that released values and released identities are handled correctly rather than defaulting to the first $ORDER match.

  • Purpose
    • Given one unique attribute and its value, determine the correct entity: an existing live owner, a freshly generated entity (value/identity released), a brand-new entity (value never claimed), or 0 (insert-unique violation / internal error).
  • Step 1 — Setup
    • Declares val, mode, ownereid, ownerIsLive, eid; initializes eid=0.
    • Reads val from ResolvedRec("+",aid).
    • Calls GetUniqueMode^sapiGet (L5, drilled into above) to get mode.
  • Step 2 — Guard: empty value
    • If val="": logs an error (internal error — empty value for unique attribute) and quits 0.
  • Step 3 — Branch: has this value ever been registered?
    • Calls IsRangeValue^sapiVld — checks whether val has ever been registered for aid. Unexpanded; body not yet pasted.
    • If yes (value previously registered):
      • Calls ResolveLiveEID (same name referenced in GetEID^apiGet above, but called here without an explicit ^routine tag in the source — presumed same ResolveLiveEID^apiRslv; unexpanded, body not yet pasted) to get ownereid.
      • Sets ownerIsLive=(ownereid'=0).
      • UNQINSERT + live owner: sets eid=0, logs an error (insert-unique violation — already owned).
      • UNQINSERT + no live owner: value is free again — calls GENID^utils (drilled into above, L4) to generate a new entity, logs debug.
      • UNQUPSERT + live owner: claimant is treated as the same real-world identity — sets eid=ownereid, logs debug (merge into existing EID).
      • UNQUPSERT + no live owner: prior identity released the value — calls GENID^utils to mint a fresh entity (does NOT merge into the dead owner), logs debug.
    • If no (value never registered at all):
      • Calls GENID^utils to generate a new entity regardless of mode, logs debug (new entity).
  • Step 4 — Quit
    • Returns eid to the caller (ResolveByUnique^apiRslv Step 5, or ResolveDesignatedUnique^apiRslv Step 6, depending on path).

L2 - ResolveTargetEntity^apiRslv flowchart

In HTML format

Mermaid format
flowchart TD
    RTEStart(["'ResolveTargetEntity^apiRslv' — Step 1:<br/>Setup, eid = 0"]) --> RTEPathCheck{"'ResolveTargetEntity^apiRslv' — Step 2:<br/>Which control attribute<br/>is present?"}

    RTEPathCheck -->|"Path 0: sys.attr.id present"| RBE["'ResolveByEID^apiRslv'<br/>resolve via explicit<br/>raw EID"]
    RTEPathCheck -->|"Path 1: sys.attr.key present"| RBNK["'ResolveByNaturalKey^apiRslv'<br/>find-or-create via<br/>natural key"]
    RTEPathCheck -->|"Path 2: neither present"| RBU["'ResolveByUnique^apiRslv'<br/>find-or-create via<br/>unique attribute"]

    RBE --> RBEStep1["Read raw EID value,<br/>kill sys.attr.id node<br/>from ResolvedRec"]
    RBEStep1 --> GetEID1["'GetEID^apiGet'<br/>validate format and<br/>existence of value"]

    GetEID1 --> GESetup["Setup, guard empty value,<br/>guard aid must be numeric"]
    GESetup --> GEPath0{"Is value<br/>EID-shaped?"}

    GEPath0 -->|"Yes"| GERegCheck["'IsEntityRegistered^apiVld'<br/>check if raw EID<br/>is registered"]
    GERegCheck --> GERegOutcome{"Registered?"}
    GERegOutcome -->|"Yes"| GEReturnEid(["Return resolved eid"])
    GERegOutcome -->|"No"| GEReturnZeroA(["Return eid = 0"])

    GEPath0 -->|"No, and aid omitted"| GEPath1["'ResolveLiveEID^apiRslv'<br/>lookup live owner via<br/>sys.attr.key"]
    GEPath1 --> GEReturnPath1(["Return eid<br/>(resolved or 0)"])

    GEPath0 -->|"No, and aid supplied"| GEPath2["'ResolveLiveEID^apiRslv'<br/>lookup live owner via<br/>unique attribute"]
    GEPath2 --> GEReturnPath2(["Return eid<br/>(resolved or 0)"])

    GEReturnEid --> RBEQuit(["'ResolveByEID^apiRslv'<br/>returns eid to<br/>ResolveTargetEntity"])
    GEReturnZeroA --> RBEQuit
    GEReturnPath1 --> RBEQuit
    GEReturnPath2 --> RBEQuit

    RBNK --> RBNKRead["Read sys.attr.key value<br/>(kept in ResolvedRec —<br/>must reach DatomAssert)"]
    RBNKRead --> GetEID2["'GetEID^apiGet'<br/>same routine as above,<br/>no aid supplied"]
    GetEID2 --> RBNKCheck{"Resolved,<br/>eid greater than 0?"}
    RBNKCheck -->|"Yes"| RBNKFound["Log resolved<br/>via sys.attr.key"]
    RBNKCheck -->|"No"| GENID1["'GENID^utils'<br/>generate new<br/>time-sorted entity ID"]
    RBNKFound --> RBNKQuit(["'ResolveByNaturalKey^apiRslv'<br/>returns eid<br/>(never fails)"])
    GENID1 --> RBNKQuit

    RBU --> CUA["'CountUniqueAttributes^apiRslv'<br/>count unique-constrained<br/>assertion attributes"]
    CUA --> GUM1["'GetUniqueMode^sapiGet'<br/>per attribute:<br/>check uniqueness mode"]
    GUM1 --> CUAReturn(["Return count,<br/>first unique aid"])

    CUAReturn --> RBUCase0{"count = 0 and<br/>resolvedby present?"}
    RBUCase0 -->|"Yes"| RBUErr1["Log error:<br/>resolvedby specified<br/>but no unique attrs"]
    RBUErr1 --> RBUReturnZero1(["Return eid = 0"])

    RBUCase0 -->|"No"| RBUCase0b{"count = 0<br/>(anonymous entity)?"}
    RBUCase0b -->|"Yes"| GENID2["'GENID^utils'<br/>generate new<br/>anonymous entity"]
    GENID2 --> RBUReturnAnon(["Return generated eid"])

    RBUCase0b -->|"No"| RBUCase1{"count = 1?"}
    RBUCase1 -->|"Yes"| RO1["'ResolveOwnership^apiRslv'<br/>apply insert/upsert<br/>semantics for sole<br/>unique attribute"]
    RO1 --> RBUReturnRO1(["Return eid from<br/>ResolveOwnership"])

    RBUCase1 -->|"No, count greater than 1"| RBUCaseMulti{"sys.attr.resolvedby<br/>present?"}
    RBUCaseMulti -->|"No"| RBUErr2["Log error:<br/>multiple unique attrs<br/>require resolvedby"]
    RBUErr2 --> RBUReturnZero2(["Return eid = 0"])

    RBUCaseMulti -->|"Yes"| RDU["'ResolveDesignatedUnique^apiRslv'<br/>validate and resolve via<br/>caller-designated attribute"]

    RDU --> RDUStep1["'GetEID^sapiGet'<br/>validate attribute key<br/>exists in schema"]
    RDUStep1 --> RDUCheck1{"Attribute<br/>registered?"}
    RDUCheck1 -->|"No"| RDUErr1["Log error:<br/>resolvedby attribute<br/>not registered"]
    RDUErr1 --> RDUReturnZero1(["Return eid = 0"])

    RDUCheck1 -->|"Yes"| GUM2["'GetUniqueMode^sapiGet'<br/>check attribute<br/>is unique"]
    GUM2 --> RDUCheck2{"Attribute<br/>is unique?"}
    RDUCheck2 -->|"No"| RDUErr2["Log error:<br/>resolvedby attribute<br/>not unique"]
    RDUErr2 --> RDUReturnZero2(["Return eid = 0"])

    RDUCheck2 -->|"Yes"| RDUCheck3{"Attribute present<br/>in record?"}
    RDUCheck3 -->|"No"| RDUErr3["Log error:<br/>resolvedby attribute<br/>missing from record"]
    RDUErr3 --> RDUReturnZero3(["Return eid = 0"])

    RDUCheck3 -->|"Yes"| RDUCheck4{"Value<br/>non-empty?"}
    RDUCheck4 -->|"No"| RDUErr4["Log error:<br/>resolvedby attribute<br/>empty value"]
    RDUErr4 --> RDUReturnZero4(["Return eid = 0"])

    RDUCheck4 -->|"Yes"| RO2["'ResolveOwnership^apiRslv'<br/>apply insert/upsert<br/>semantics for<br/>designated attribute"]
    RO2 --> RDUReturnRO2(["Return eid from<br/>ResolveOwnership"])

    RDUReturnRO2 --> RBUKillNode["Kill sys.attr.resolvedby<br/>node from ResolvedRec"]
    RBUKillNode --> RBUQuitFinal(["'ResolveByUnique^apiRslv'<br/>returns eid to<br/>ResolveTargetEntity"])

    RBUReturnZero1 --> RBUQuitFinal2(["'ResolveByUnique^apiRslv'<br/>returns eid = 0"])
    RBUReturnAnon --> RBUQuitFinal
    RBUReturnRO1 --> RBUQuitFinal
    RBUReturnZero2 --> RBUQuitFinal2

    subgraph RO["ResolveOwnership^apiRslv internals"]
        ROStart["Setup: read val,<br/>get uniqueness mode"] --> ROEmptyCheck{"Value<br/>empty?"}
        ROEmptyCheck -->|"Yes"| ROErrEmpty["Log error:<br/>internal error,<br/>empty value"]
        ROErrEmpty --> ROReturnZero(["Return eid = 0"])

        ROEmptyCheck -->|"No"| RORangeCheck{"'IsRangeValue^sapiVld'<br/>has value ever<br/>been registered?"}

        RORangeCheck -->|"No, never registered"| ROGenNew["'GENID^utils'<br/>generate new entity"]
        ROGenNew --> ROReturnNew(["Return generated eid"])

        RORangeCheck -->|"Yes, previously registered"| ROLiveCheck["'ResolveLiveEID'<br/>find current live<br/>owner of value"]
        ROLiveCheck --> ROModeCheck{"Mode and<br/>owner liveness?"}

        ROModeCheck -->|"UNQINSERT,<br/>owner live"| ROViolation["Log error:<br/>insert-unique<br/>violation"]
        ROViolation --> ROReturnViolation(["Return eid = 0"])

        ROModeCheck -->|"UNQINSERT,<br/>no live owner"| ROInsertFree["'GENID^utils'<br/>value released,<br/>generate new entity"]
        ROInsertFree --> ROReturnInsertFree(["Return generated eid"])

        ROModeCheck -->|"UNQUPSERT,<br/>owner live"| ROMerge["Merge into<br/>existing live owner"]
        ROMerge --> ROReturnMerge(["Return owner eid"])

        ROModeCheck -->|"UNQUPSERT,<br/>no live owner"| ROUpsertFree["'GENID^utils'<br/>identity released,<br/>generate new entity"]
        ROUpsertFree --> ROReturnUpsertFree(["Return generated eid"])
    end

    RO1 -.-> ROStart
    RO2 -.-> ROStart