FastPrepCallback Signal Registry

Callback Signal Registry

Candid Health logoCandid Health● MediumFULLTIMEPHONE SCREEN
Learn

Problem statement

Implement a callback registry keyed by signal ID. Process the finite batch operations in order. Every callback ID has one row in callbackBehaviors.

Operations

  • ["REGISTER", signalId, callbackId]: add the callback to that signal. A signal contains each callback ID at most once. Return ["REGISTERED"], or ["ALREADY_REGISTERED"] when it is already present.
  • ["UNREGISTER", signalId, callbackId]: remove that callback identity. Return ["UNREGISTERED"], or ["NOT_FOUND"] when it is absent.
  • ["SIGNAL", signalId]: dispatch the signal and return its invocation events as described below.

Registration order is significant. Removing a callback preserves the relative order of all others; registering it later appends it to the end.

Callback behaviors

Each behavior row is [callbackId, outcome, nestedSignalId, nestedSignalLimit]. outcome is "OK" or "THROW". A nested signal ID of "-" means that callback never signals another key. Otherwise, its first nestedSignalLimit invocations enqueue that signal. The invocation count is global across the whole operation batch.

A SIGNAL operation uses a FIFO queue initialized with its signal ID. For each dequeued signal, take a snapshot of its callback IDs in current registration order and invoke that snapshot completely. Nested signals join the back of the queue, so reentrant work never interrupts the current snapshot. Each later queued signal takes a fresh snapshot.

When a callback invokes a nested signal and has outcome "THROW", the nested signal is enqueued before the callback error is recorded. An error never stops the rest of the current snapshot or the queued signals.

Record each invocation as signalId:callbackId:OK or signalId:callbackId:ERROR. One SIGNAL row contains every event produced while its queue drains. Signaling a key with no callbacks returns an empty row. Return exactly one output row per input operation.

Function

processCallbackSignals(operations: String[][], callbackBehaviors: String[][]) → String[][]

Examples

Example 1

operations = [["REGISTER","invoice","audit"],["REGISTER","invoice","notify"],["REGISTER","invoice","metrics"],["SIGNAL","invoice"],["UNREGISTER","invoice","notify"],["SIGNAL","invoice"]]callbackBehaviors = [["audit","OK","-","0"],["notify","THROW","-","0"],["metrics","OK","-","0"]]return = [["REGISTERED"],["REGISTERED"],["REGISTERED"],["invoice:audit:OK","invoice:notify:ERROR","invoice:metrics:OK"],["UNREGISTERED"],["invoice:audit:OK","invoice:metrics:OK"]]

Callbacks run in registration order. The failing notify callback is recorded as an error, but metrics still runs. After removal, the remaining order is unchanged.

Example 2

operations = [["REGISTER","ready","first"],["REGISTER","ready","second"],["REGISTER","ready","first"],["UNREGISTER","ready","first"],["REGISTER","ready","first"],["SIGNAL","ready"]]callbackBehaviors = [["first","OK","-","0"],["second","OK","-","0"]]return = [["REGISTERED"],["REGISTERED"],["ALREADY_REGISTERED"],["UNREGISTERED"],["REGISTERED"],["ready:second:OK","ready:first:OK"]]

A duplicate registration is a no-op. Removing and registering first again appends it after second.

Example 3

operations = [["REGISTER","alpha","a"],["REGISTER","alpha","b"],["REGISTER","beta","c"],["SIGNAL","alpha"]]callbackBehaviors = [["a","OK","beta","1"],["b","THROW","alpha","1"],["c","OK","-","0"]]return = [["REGISTERED"],["REGISTERED"],["REGISTERED"],["alpha:a:OK","alpha:b:ERROR","beta:c:OK","alpha:a:OK","alpha:b:ERROR"]]

The first alpha dispatch queues beta and then another alpha. FIFO draining finishes the current snapshot first. Each callback's one-signal limit then prevents another cycle.

Constraints

  • 0 <= operations.length <= 100000.
  • 0 <= callbackBehaviors.length <= 100000.
  • Every operation has exactly one of the three forms above, and every registered callback ID has exactly one behavior row.
  • Signal IDs and callback IDs contain 1 to 20 lowercase ASCII letters, digits, or underscores, and do not contain colons. Callback IDs are unique in callbackBehaviors.
  • outcome is "OK" or "THROW". nestedSignalLimit is a decimal integer from 0 through 10; it is 0 when nestedSignalId is "-".
  • The sum of all nested-signal limits is at most 100000.
  • The total number of callback invocation events produced by the batch is at most 200000.
See Candid Health hiring insights
public String[][] processCallbackSignals(String[][] operations, String[][] callbackBehaviors) {
    // Write your code here.
}
operations[["REGISTER","invoice","audit"],["REGISTER","invoice","notify"],["REGISTER","invoice","metrics"],["SIGNAL","invoice"],["UNREGISTER","invoice","notify"],["SIGNAL","invoice"]]
callbackBehaviors[["audit","OK","-","0"],["notify","THROW","-","0"],["metrics","OK","-","0"]]
expected[["REGISTERED"], ["REGISTERED"], ["REGISTERED"], ["invoice:audit:OK", "invoice:notify:ERROR", "invoice:metrics:OK"], ["UNREGISTERED"], ["invoice:audit:OK", "invoice:metrics:OK"]]
Checking account…