Repository navigation
Enforce promise id format origin:lineage, remove RESONATE_PREFIX - #12
Merged
Merged
Conversation
- Ids are <origin>:<lineage>: the caller-supplied root id is the origin,
lineage segments below it are '.'-separated (root -> root:1 -> root:1.1).
- Remove RESONATE_PREFIX env var and Builder.prefix support; drop the
resonate:prefix tag.
- Reject the reserved separators ':' and '.' in run/rpc/schedule ids at the
call site (InvalidIdError); get is a lookup and does not validate.
- Detached ids are {origin}:d{16hex}, minted off the lineage origin (kept from
the parent) with resonate:parent = origin, so recursion stays bounded and
every id in a lineage shares one origin.
- Adapt ctx.sleep to the server's target-gated timeouts: timers carry a
resonate:target, Core drops/short-circuits timer tasks, LocalNetwork
mirrors the server's only-targeted-promises-time-out invariant.
- Schedule promise-id template is now {{.id}}-{{.timestamp}}.
Mirrors resonate-sdk-py ec67529; matches the server's id rules
(resonatehq/resonate 'new promise id', #1127) and the colon_in_origin guard
(server commit d6fae28).
'.' separates lineage segments *below* the origin, which are only ever read
once the origin has been split off at the first ':'. A dotted root id is
therefore unambiguous and round-trips intact:
my.app.workflow -> my.app.workflow:1 -> my.app.workflow:1.1
Only ':' stays reserved: the origin is everything before an id's first ':',
so an origin holding one could never be split back out of any id
(colon_in_origin).
The server's dot_in_origin guard -- a leftover from when '.' was the only
separator -- is dropped alongside this (resonatehq/resonate src/types.rs);
colon_in_origin stays. The ported server rules in the id-format tests drop
their dot_in_origin assertion to match, and the workflow compliance test now
also replays every minted id under a dotted root.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Ports the promise id format change to the Java SDK, mirroring resonate-sdk-py
ec67529(see also the server'snew promise idrules, resonatehq/resonate#1127, and itscolon_in_originguard, commitd6fae28).Every promise id is now
<origin>:<lineage>: the origin (before the first:) is the caller-supplied workflow id, and the lineage segments below it are.-separated::and.are therefore reserved and rejected in caller-supplied root ids.1.
RESONATE_PREFIXsupport removed (breaking)Resonate.builder().prefix(...)removed; theRESONATE_PREFIXenv var is no longer read.{prefix}:{id}— the id you pass torun/rpc/get/scheduleis the id you get.resonate:prefixtag is no longer emitted on any promise.2. Id minting follows the server's separator rule
New
Ids.java:joinId(a bare root joins its first lineage segment with:, deeper ones with.),originOf(everything before the first:, mirroring the server'sorigin()), andvalidateRootId.Context.java— child ids minted withjoinId; theprefixIdplumbing is gone (the origin now doubles as the id-generation anchor).ctx.detachedmints{origin}:d{16hex}and keeps the parent's origin (the server requires every id in a lineage to extend its origin), declaring the origin as itsresonate:parent; recursion stays bounded at one segment past the origin.Core.java— the root context's origin comes from theresonate:origintag, falling back toIds.originOf(promise.id())for tag-less promises (same derivation the server uses).Resonate.java— top-level promise tags are noworigin == branch == parent == id(noresonate:prefix).3.
:(and.) rejected in user-supplied idsrun,rpc, andschedulevalidate the id at the call site and throwInvalidIdError(new,Errors.java) instead of surfacing an opaque 400 from a background create.getis a lookup and deliberately does not validate (it accepts child ids likewf:1.2).scheduletemplates the fired promise id as{{.id}}-{{.timestamp}}(previously.-joined): the server stamps the whole templated id as the fired promise's origin, so it must stay a single bare segment.4. Durable sleep vs target-gated timeouts
Since server commit
c8d7c7bthe scheduler only times out promises carrying aresonate:target; a target-lessctx.sleeppromise would never fire.Context.java—ctx.sleeptimer promises now carry aresonate:target;resonate:timermakes the deadline settle the promise resolved, which wakes the sleepers.Core.java— the target also spawns a task dispatched immediately; a timer names no function, so Core drops a task for a still-pending timer (no fulfill, no suspend, no release) and short-circuits a settled timer's task before theTaskDatadecode.Network.java—LocalNetworknow mirrors the server's invariant (only targeted promises are scheduled for timeout), so this class of bug fails locally instead of only against a real server.Examples
structuredconcurrency,humanintheloop— child-id comments/lookups updated to{id}:1shape.Tests
IdFormatTest.java(new) — a direct port of the server'svalidate_promise_create_data/origin(); every promise the SDK creates is replayed through it, plusjoinId/originOf/validateRootId, detached id shape, and call-site rejection tests.CoreTest— timer-task tests (drop pending, short-circuit settled, deadline scheduled by the server).NetworkTest— scheduler invariant: only targeted promises are timed out;resonate:timersettles resolved.root:1shape throughout.Verification
./gradlew test— all pass./gradlew spotlessCheck— clean