Skip to content

Refactor createReactiveStoreWithInitialValueAndSlotTracking to use store inputs#1708

Open
mcintyre94 wants to merge 1 commit into
react/depend-on-kitfrom
rpc/sendable-subscribable
Open

Refactor createReactiveStoreWithInitialValueAndSlotTracking to use store inputs#1708
mcintyre94 wants to merge 1 commit into
react/depend-on-kitfrom
rpc/sendable-subscribable

Conversation

@mcintyre94

@mcintyre94 mcintyre94 commented May 27, 2026

Copy link
Copy Markdown
Member

Note: this PR has been rewritten, first review comments refer to an old version

Problem

createReactiveStoreWithInitialValueAndSlotTracking currently takes as input a PendingRpcRequest and a PendingRpcSubscriptionsRequest. Internally it is using the send() and subscribe() functions, and not the reactiveStore() that is used by the react hooks.

Summary of Changes

createReactiveStoreWithInitialValueAndSlotTracking is refactored to take a ReactiveActionStore and a ReactiveStreamStore, and its internals are rewritten to produce its store from these inputs.

Its config now has the shape:

{
    initialValueSource: ReactiveActionSource<SolanaRpcResponse<TInitialValue>>;
    initialValueMapper: (value: TInitialValue) => TItem;
    streamSource: ReactiveStreamSource<SolanaRpcResponse<TStreamValue>>;
    streamValueMapper: (value: TStreamValue) => TItem;
}

Its behaviour is unchanged - it combines the initial value and the stream and always provides the latest available data (based on slot) from either source

The following PR adds a react hook that exposes createReactiveStoreWithInitialValueAndSlotTracking, and it will now share the same input types with the other react hooks.

@changeset-bot

changeset-bot Bot commented May 27, 2026

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: d13eb87

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 47 packages
Name Type
@solana/kit Major
@solana/react Major
@solana/accounts Major
@solana/addresses Major
@solana/assertions Major
@solana/codecs-core Major
@solana/codecs-data-structures Major
@solana/codecs-numbers Major
@solana/codecs-strings Major
@solana/codecs Major
@solana/compat Major
@solana/errors Major
@solana/fast-stable-stringify Major
@solana/fixed-points Major
@solana/functional Major
@solana/instruction-plans Major
@solana/instructions Major
@solana/keys Major
@solana/nominal-types Major
@solana/offchain-messages Major
@solana/options Major
@solana/plugin-core Major
@solana/plugin-interfaces Major
@solana/program-client-core Major
@solana/programs Major
@solana/promises Major
@solana/rpc-api Major
@solana/rpc-graphql Major
@solana/rpc-parsed-types Major
@solana/rpc-spec-types Major
@solana/rpc-spec Major
@solana/rpc-subscriptions-api Major
@solana/rpc-subscriptions-channel-websocket Major
@solana/rpc-subscriptions-spec Major
@solana/rpc-subscriptions Major
@solana/rpc-transformers Major
@solana/rpc-transport-http Major
@solana/rpc-types Major
@solana/rpc Major
@solana/signers Major
@solana/subscribable Major
@solana/sysvars Major
@solana/transaction-confirmation Major
@solana/transaction-messages Major
@solana/transactions Major
@solana/wallet-account-signer Major
@solana/webcrypto-ed25519-polyfill Major

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

mcintyre94 commented May 27, 2026

Copy link
Copy Markdown
Member Author

@bundlemon

bundlemon Bot commented May 27, 2026

Copy link
Copy Markdown

BundleMon

Files updated (25)
Status Path Size Limits
react/dist/index.browser.mjs
5KB (+1.9KB +61.5%) -
react/dist/index.native.mjs
5KB (+1.9KB +61.52%) -
react/dist/index.node.mjs
5KB (+1.9KB +61.54%) -
@solana/kit production bundle
kit/dist/index.production.min.js
53.01KB (+415B +0.77%) -
kit/dist/index.browser.mjs
4.79KB (+331B +7.23%) -
kit/dist/index.native.mjs
4.79KB (+331B +7.23%) -
kit/dist/index.node.mjs
4.79KB (+331B +7.23%) -
errors/dist/index.browser.mjs
20.9KB (+179B +0.84%) -
errors/dist/index.native.mjs
20.9KB (+179B +0.84%) -
errors/dist/index.node.mjs
20.92KB (+179B +0.84%) -
wallet-account-signer/dist/index.browser.mjs
17.69KB (+169B +0.94%) -
wallet-account-signer/dist/index.native.mjs
17.69KB (+168B +0.94%) -
wallet-account-signer/dist/index.node.mjs
17.71KB (+168B +0.93%) -
subscribable/dist/index.browser.mjs
2.76KB (+160B +6%) -
subscribable/dist/index.native.mjs
2.77KB (+160B +5.99%) -
subscribable/dist/index.node.mjs
2.83KB (+158B +5.76%) -
rpc-types/dist/index.browser.mjs
1.9KB (+102B +5.53%) -
rpc-types/dist/index.native.mjs
1.9KB (+101B +5.48%) -
rpc-types/dist/index.node.mjs
1.9KB (+101B +5.48%) -
rpc-subscriptions-spec/dist/index.browser.mjs
2.19KB (-13B -0.58%) -
rpc-subscriptions-spec/dist/index.native.mjs
2.19KB (-13B -0.58%) -
rpc-subscriptions-spec/dist/index.node.mjs
2.23KB (-13B -0.56%) -
rpc-spec/dist/index.browser.mjs
898B (-20B -2.18%) -
rpc-spec/dist/index.native.mjs
897B (-21B -2.29%) -
rpc-spec/dist/index.node.mjs
896B (-21B -2.29%) -
Unchanged files (122)
Status Path Size Limits
rpc-graphql/dist/index.browser.mjs
18.82KB -
rpc-graphql/dist/index.native.mjs
18.81KB -
rpc-graphql/dist/index.node.mjs
18.81KB -
transaction-messages/dist/index.browser.mjs
11.32KB -
transaction-messages/dist/index.native.mjs
11.32KB -
transaction-messages/dist/index.node.mjs
11.32KB -
instruction-plans/dist/index.browser.mjs
6.58KB -
instruction-plans/dist/index.native.mjs
6.58KB -
instruction-plans/dist/index.node.mjs
6.58KB -
fixed-points/dist/index.browser.mjs
5.08KB -
fixed-points/dist/index.native.mjs
5.07KB -
fixed-points/dist/index.node.mjs
5.07KB -
codecs-data-structures/dist/index.browser.mjs
5.04KB -
codecs-data-structures/dist/index.native.mjs
5.03KB -
codecs-data-structures/dist/index.node.mjs
5.03KB -
offchain-messages/dist/index.browser.mjs
4.89KB -
offchain-messages/dist/index.native.mjs
4.89KB -
offchain-messages/dist/index.node.mjs
4.89KB -
transactions/dist/index.browser.mjs
4.07KB -
transactions/dist/index.native.mjs
4.07KB -
transactions/dist/index.node.mjs
4.07KB -
codecs-core/dist/index.browser.mjs
3.62KB -
codecs-core/dist/index.native.mjs
3.62KB -
codecs-core/dist/index.node.mjs
3.62KB -
webcrypto-ed25519-polyfill/dist/index.node.mj
s
3.61KB -
webcrypto-ed25519-polyfill/dist/index.browser
.mjs
3.59KB -
webcrypto-ed25519-polyfill/dist/index.native.
mjs
3.57KB -
rpc-subscriptions/dist/index.browser.mjs
3.37KB -
rpc-subscriptions/dist/index.node.mjs
3.34KB -
rpc-subscriptions/dist/index.native.mjs
3.31KB -
signers/dist/index.browser.mjs
3.26KB -
signers/dist/index.native.mjs
3.26KB -
signers/dist/index.node.mjs
3.26KB -
rpc-transformers/dist/index.browser.mjs
3.16KB -
rpc-transformers/dist/index.native.mjs
3.16KB -
rpc-transformers/dist/index.node.mjs
3.16KB -
keys/dist/index.node.mjs
3.06KB -
addresses/dist/index.browser.mjs
2.93KB -
addresses/dist/index.native.mjs
2.92KB -
addresses/dist/index.node.mjs
2.92KB -
keys/dist/index.browser.mjs
2.85KB -
keys/dist/index.native.mjs
2.85KB -
codecs-strings/dist/index.browser.mjs
2.55KB -
codecs-strings/dist/index.node.mjs
2.51KB -
codecs-strings/dist/index.native.mjs
2.47KB -
transaction-confirmation/dist/index.node.mjs
2.42KB -
transaction-confirmation/dist/index.native.mj
s
2.37KB -
sysvars/dist/index.browser.mjs
2.37KB -
sysvars/dist/index.native.mjs
2.37KB -
transaction-confirmation/dist/index.browser.m
js
2.37KB -
sysvars/dist/index.node.mjs
2.37KB -
rpc/dist/index.node.mjs
1.95KB -
codecs-numbers/dist/index.browser.mjs
1.95KB -
codecs-numbers/dist/index.native.mjs
1.95KB -
codecs-numbers/dist/index.node.mjs
1.94KB -
rpc-transport-http/dist/index.browser.mjs
1.89KB -
rpc-transport-http/dist/index.native.mjs
1.89KB -
rpc/dist/index.native.mjs
1.81KB -
rpc/dist/index.browser.mjs
1.8KB -
rpc-transport-http/dist/index.node.mjs
1.71KB -
rpc-subscriptions-channel-websocket/dist/inde
x.node.mjs
1.33KB -
rpc-subscriptions-channel-websocket/dist/inde
x.native.mjs
1.27KB -
rpc-subscriptions-channel-websocket/dist/inde
x.browser.mjs
1.26KB -
program-client-core/dist/index.browser.mjs
1.21KB -
program-client-core/dist/index.native.mjs
1.21KB -
program-client-core/dist/index.node.mjs
1.21KB -
options/dist/index.browser.mjs
1.18KB -
options/dist/index.native.mjs
1.18KB -
options/dist/index.node.mjs
1.17KB -
accounts/dist/index.browser.mjs
1.17KB -
accounts/dist/index.native.mjs
1.17KB -
accounts/dist/index.node.mjs
1.16KB -
rpc-api/dist/index.browser.mjs
998B -
rpc-api/dist/index.native.mjs
997B -
rpc-api/dist/index.node.mjs
995B -
compat/dist/index.browser.mjs
969B -
compat/dist/index.native.mjs
968B -
compat/dist/index.node.mjs
966B -
rpc-spec-types/dist/index.browser.mjs
962B -
rpc-spec-types/dist/index.native.mjs
961B -
rpc-spec-types/dist/index.node.mjs
959B -
rpc-subscriptions-api/dist/index.native.mjs
871B -
rpc-subscriptions-api/dist/index.browser.mjs
870B -
rpc-subscriptions-api/dist/index.node.mjs
870B -
promises/dist/index.native.mjs
841B -
promises/dist/index.node.mjs
840B -
promises/dist/index.browser.mjs
839B -
plugin-core/dist/index.browser.mjs
820B -
plugin-core/dist/index.native.mjs
819B -
plugin-core/dist/index.node.mjs
817B -
assertions/dist/index.browser.mjs
783B -
instructions/dist/index.browser.mjs
771B -
instructions/dist/index.native.mjs
770B -
instructions/dist/index.node.mjs
768B -
fast-stable-stringify/dist/index.browser.mjs
726B -
fast-stable-stringify/dist/index.native.mjs
725B -
assertions/dist/index.native.mjs
724B -
fast-stable-stringify/dist/index.node.mjs
724B -
assertions/dist/index.node.mjs
723B -
programs/dist/index.browser.mjs
329B -
programs/dist/index.native.mjs
327B -
programs/dist/index.node.mjs
325B -
fs-impl/dist/index.browser.mjs
245B -
event-target-impl/dist/index.node.mjs
230B -
functional/dist/index.browser.mjs
154B -
functional/dist/index.native.mjs
152B -
text-encoding-impl/dist/index.native.mjs
152B -
functional/dist/index.node.mjs
151B -
codecs/dist/index.browser.mjs
145B -
codecs/dist/index.native.mjs
144B -
codecs/dist/index.node.mjs
142B -
event-target-impl/dist/index.browser.mjs
133B -
ws-impl/dist/index.node.mjs
131B -
text-encoding-impl/dist/index.browser.mjs
122B -
fs-impl/dist/index.node.mjs
120B -
text-encoding-impl/dist/index.node.mjs
119B -
ws-impl/dist/index.browser.mjs
113B -
crypto-impl/dist/index.node.mjs
111B -
crypto-impl/dist/index.browser.mjs
109B -
rpc-parsed-types/dist/index.browser.mjs
66B -
rpc-parsed-types/dist/index.native.mjs
65B -
rpc-parsed-types/dist/index.node.mjs
63B -

Total files change +8.77KB +1.66%

Final result: ✅

View report in BundleMon website ➡️


Current branch size history | Target branch size history

@github-actions

github-actions Bot commented May 27, 2026

Copy link
Copy Markdown
Contributor

Documentation Preview: https://kit-docs-hll1l7wr6-anza-tech.vercel.app

@mcintyre94 mcintyre94 force-pushed the rpc/sendable-subscribable branch from c71602b to 4399c85 Compare May 27, 2026 16:08
@mcintyre94

Copy link
Copy Markdown
Member Author

@trevor-cortex

@trevor-cortex trevor-cortex left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM (commenting because I can't formally approve without explicit repo access).

Summary

Adds two structural duck-types — RpcSendable<TResponse> (just send(options?)) in @solana/rpc-spec and RpcSubscribable<TNotification> (just subscribe(options)) in @solana/rpc-subscriptions-spec — and uses them to loosen the rpcRequest / rpcSubscriptionRequest fields on the configs for createReactiveStoreWithInitialValueAndSlotTracking and createAsyncGeneratorWithInitialValueAndSlotTracking. Both primitives only ever call .send() / .subscribe() on those inputs, so the narrower types are sufficient and existing callers continue to work because PendingRpcRequest / PendingRpcSubscriptionsRequest structurally satisfy the new types.

Mirrors the prior-art pattern from ReactiveActionSource / ReactiveStreamSource, and makes life easier for plugin authors / test mocks that don't want to fabricate a full { reactiveStore, send } object.

What I verified

  • The new RpcSendable.send signature is identical to PendingRpcRequest.send (send(options?: RpcSendOptions): Promise<TResponse>), and RpcSubscribable.subscribe is identical to PendingRpcSubscriptionsRequest.subscribe (subscribe(options: RpcSubscribeOptions): Promise<AsyncIterable<TNotification>>) — so structural compatibility actually holds and existing call sites compile unchanged.
  • The new types flow through to @solana/kit via the existing export * chains (rpc-specrpckit, rpc-subscriptions-specrpc-subscriptionskit), matching the changeset's documented import type { RpcSendable, RpcSubscribable } from '@solana/kit' example.
  • Both implementation files only consume .send() / .subscribe() on these inputs, so loosening the type is purely additive at runtime.
  • Docblock copy on the two config fields was updated from "A pending RPC request" → "A one-shot RPC request" / "An RPC subscription request", which more accurately describes the looser contract.

Changeset

minor across @solana/rpc-spec, @solana/rpc-subscriptions-spec, and @solana/kit looks right — purely additive new exports plus a contravariant input loosening, no breaking change. Fixed-version lockstep handles the umbrella @solana/rpc / @solana/rpc-subscriptions packages automatically.

Notes for subsequent reviewers

  • Worth a quick sanity check that no downstream consumer is relying on the specific PendingRpcRequest / PendingRpcSubscriptionsRequest shape on the config (e.g. calling .reactiveStore() on the passed-in object). A grep over rpcRequest.reactiveStore / rpcSubscriptionRequest.reactiveStore in this repo and kit-plugins should be enough.
  • No tests changed. Given this is type-only and the structural relationship is mechanically obvious, that's fine — but if there's a __typetests__ directory for these primitives, a one-liner asserting that a Pending*Request is assignable to the new config (and that a bare { send } / { subscribe } object also is) would lock in the contract cheaply.

@mcintyre94 mcintyre94 force-pushed the rpc/sendable-subscribable branch from 4399c85 to d303d3d Compare May 27, 2026 16:43
@mcintyre94 mcintyre94 marked this pull request as ready for review May 27, 2026 16:58
@mcintyre94 mcintyre94 force-pushed the rpc/sendable-subscribable branch from d303d3d to eb7e142 Compare May 28, 2026 10:03
@mcintyre94 mcintyre94 force-pushed the react/depend-on-kit branch 2 times, most recently from b81de7d to f0abc4e Compare May 28, 2026 10:06
@mcintyre94 mcintyre94 force-pushed the rpc/sendable-subscribable branch 2 times, most recently from 0153a07 to e40f088 Compare May 28, 2026 10:13
@mcintyre94 mcintyre94 force-pushed the react/depend-on-kit branch from f0abc4e to 5dc6620 Compare May 28, 2026 10:13
@mcintyre94 mcintyre94 changed the base branch from react/depend-on-kit to graphite-base/1708 May 28, 2026 12:55
@mcintyre94 mcintyre94 force-pushed the graphite-base/1708 branch from 5dc6620 to 72ffd52 Compare May 28, 2026 13:30
@mcintyre94 mcintyre94 force-pushed the rpc/sendable-subscribable branch from e40f088 to 1ec107f Compare May 28, 2026 13:30
@mcintyre94 mcintyre94 changed the base branch from graphite-base/1708 to react/depend-on-kit May 28, 2026 13:31
@mcintyre94 mcintyre94 force-pushed the rpc/sendable-subscribable branch 4 times, most recently from 4ba1928 to b50eb7f Compare May 29, 2026 15:49
@mcintyre94 mcintyre94 changed the title Add RpcSendable / RpcSubscribable duck-types and loosen reactive-store config Refactor createReactiveStoreWithInitialValueAndSlotTracking to use store inputs May 29, 2026
@mcintyre94 mcintyre94 requested a review from trevor-cortex May 29, 2026 15:56

@trevor-cortex trevor-cortex left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Re-review (rewritten PR)

LGTM on the new shape — this is the right pivot in response to Loris's comment, and the design holds together cleanly. Commenting because I can't formally approve.

What changed since last review

The PR no longer adds RpcSendable / RpcSubscribable to rpc-spec / rpc-subscriptions-spec. Instead createReactiveStoreWithInitialValueAndSlotTracking is rewritten to consume two reactive sourcesReactiveActionSource for the one-shot fetch and ReactiveStreamSource for the ongoing stream — calling reactiveStore() on each per connection window and forwarding their state into the unified store. The previous rpcRequest / rpcSubscriptionRequest (+ matching mappers) config fields are renamed to initialValueSource / streamSource (+ initialValueMapper / streamValueMapper). Behaviour is preserved.

Net effect: this primitive now lives entirely in the reactive-store universe (matching the React hooks), and send() / subscribe() are no longer called directly anywhere in the slot-tracking helper.

What I verified

  • PendingRpcRequest / PendingRpcSubscriptionsRequest still slot in unchanged. Both already expose reactiveStore(), so the changeset's claim that callers can still pass rpc.getBalance(addr) / rpcSubscriptions.accountNotifications(addr) directly holds. The example app diff confirms this — the only call-site change is the field renames (plus an explicit withSignal(...).connect(), which is the new required entry point).
  • Lifecycle plumbing is sound. performConnect builds fresh inner action + stream stores on every (re)connect, subscribes to both, registers a single innerSignal 'abort' listener that unsubscribes both, and then kicks them via withSignal(signal).connect() / .dispatch() where signal is the composed inner+caller signal. On supersede/reset/caller-abort, the inner controller fires, the unsubscribe listener runs, and the inner stores are orphaned with their own connections cancelled by the same signal — no listener leak, no double state writes (the existing handleError signal.aborted guard + currentState.status === 'error' guard cover the late-error race).
  • Slot tracking centralised. handleSlottedValue now applies the slot < lastUpdateSlot skip to both sources symmetrically (previously the RPC path and subscription path each had their own copy), and lastUpdateSlot still resets in performReset. The “older RPC arrives after newer subscription” / “older subscription arrives after newer RPC” tests still pass against this unified path.
  • Inner-store API choice is correct. The action subscriber reads actionStore.getState() (which returns the discriminated ReactiveActionState), and the stream subscriber reads streamStore.getUnifiedState() (the non-deprecated stream API). The deprecated getState() / getError() on ReactiveStreamStore aren't used internally.
  • Tests rewritten against real inner stores. The mocks now back initialValueSource with a real createReactiveActionStore over a controllable promise factory, and streamSource with a real createReactiveStoreFromDataPublisherFactory over a mock DataPublisher. That's a strictly better test than the previous hand-rolled send / subscribe mocks — it exercises the actual contract instead of asserting against a fake.
  • expect.assertions(n) only on async tests, fake timers + await jest.runAllTimersAsync() for flushing, Promise.withResolvers — all matches CLAUDE.md's testing conventions.
  • Changeset bump. major for @solana/kit is right: rpcRequest / rpcSubscriptionRequest (and their matching mappers) are gone from the config, so any existing caller breaks at compile time. Fixed-version lockstep will propagate the bump to the rest of the publishable packages automatically — no need to list them individually.
  • README + example app + JSDoc all consistently use the new field names and the explicit withSignal(...).connect() entry point. The example app's withSignal(abortController.signal).connect() line is the one behavioural call-site change worth flagging to next reviewers — previously the abort signal was implicitly carried by the PendingRpc*Request; now it has to be threaded explicitly.

Minor nits (non-blocking)

  • The block comment above const actionStore = initialValueSource.reactiveStore() (in create-reactive-store-with-initial-value-and-slot-tracking.ts, around the new L188–L191) still says “Both stores only ever expose send() / subscribe()-equivalent work through their reactive contract.” That's a leftover from the prior approach and reads as if the helper is still wrapping send / subscribe directly. Could be simplified to something like: “Build fresh inner stores for this connection window and forward their state into the unified store. Drive both with the composed signal so they tear down when this connection window does.” Inline comment below.
  • The cleanup comment // Note: don't call reset here, causes a race with the abort reason is slightly cryptic — worth a one-line elaboration so a future reader doesn't try to “fix” it by adding reset() calls and break the abort-reason propagation. Inline comment below.
  • Test file imports ReactiveActionSource / ReactiveStreamSource as values rather than import type. They're only used in type positions in the test file, so import type would be marginally cleaner — but verbatimModuleSyntax isn't on, so this is purely stylistic. Non-blocking.

Notes for subsequent reviewers

  • Worth thinking about: there's now no public test that exercises a PendingRpcRequest / PendingRpcSubscriptionsRequest actually being passed in as the source. The test suite uses synthetic ReactiveActionSource / ReactiveStreamSource objects. The structural relationship is mechanical (both pending-request types expose reactiveStore(): ReactiveActionStore<[], T> / reactiveStore(): ReactiveStreamStore<T>), but a one-liner __typetests__ asserting PendingRpcRequest<SolanaRpcResponse<T>> satisfies ReactiveActionSource<SolanaRpcResponse<T>> (and the subscription equivalent) on the config type would lock the duck-type contract in cheaply and survive any future signature drift on PendingRpc*Request.
  • Behavioural call-site delta to call out in release notes: prior callers that relied on the implicit caller-signal propagation through PendingRpc*Request now need an explicit withSignal(signal).connect(). The example app diff shows exactly this. The changeset entry is clear about the API rename but doesn't explicitly call out the connect-now-required-to-fire bit — might be worth a sentence.

// something newer before leaving `loading`.
function handleSlottedValue({ context: { slot }, value }: SolanaRpcResponse<TItem>) {
if (signal.aborted) return;
if (slot < lastUpdateSlot) return;

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: this comment is a leftover from the previous send() / subscribe()-based implementation and reads as if the helper is still wrapping those calls directly. Now that we're consuming the reactive-store contract instead, something like:

Build fresh inner stores for this connection window and forward their state into the unified store. Drive both with the composed signal so they tear down when this connection window does.

would more accurately describe what the block is doing. Non-blocking.

(Anchoring on the last line of the comment block — confirm the new wording lines up with whatever you settle on.)

if (state.status === 'loaded') {
const { context, value } = state.data;
handleSlottedValue({ context, value: streamValueMapper(value) });
} else if (state.status === 'error') {

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: worth a one-line elaboration here so a future reader doesn't try to “improve” this by calling actionStore.reset() / streamStore.reset() and accidentally clobber the caller-signal abort reason. Something like:

Don't call reset() on the inner stores — that would set them to idle synchronously, which races the abort-reason error transition already in flight on the composed signal and can drop the caller's abort reason on the floor.

(or whatever the actual failure mode you saw was — that's my best guess from reading the surrounding code). Non-blocking.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think the comment this is referring to is: "// Note: don't call reset here, causes a race with the abort reason"

I think this is fine and enough to tell someone not to call reset, we don't need to detail how the race happens

@mcintyre94 mcintyre94 force-pushed the rpc/sendable-subscribable branch from b50eb7f to 3cc903c Compare May 30, 2026 12:58
@mcintyre94 mcintyre94 marked this pull request as ready for review May 30, 2026 12:58
@mcintyre94 mcintyre94 requested a review from lorisleiva May 30, 2026 12:58
@mcintyre94 mcintyre94 force-pushed the rpc/sendable-subscribable branch from 3cc903c to 7c048b2 Compare June 3, 2026 15:17
@mcintyre94 mcintyre94 force-pushed the react/depend-on-kit branch from fd51da0 to 6c7bd1d Compare June 3, 2026 15:17
@mcintyre94 mcintyre94 force-pushed the rpc/sendable-subscribable branch from 7c048b2 to e8f4058 Compare June 5, 2026 15:39
@mcintyre94 mcintyre94 force-pushed the react/depend-on-kit branch from 8dc7e3a to e63a414 Compare June 5, 2026 15:47
@mcintyre94 mcintyre94 force-pushed the rpc/sendable-subscribable branch from e8f4058 to 7333125 Compare June 5, 2026 15:47
@mcintyre94 mcintyre94 force-pushed the react/depend-on-kit branch from e63a414 to 183fcb1 Compare June 5, 2026 15:56
@mcintyre94 mcintyre94 force-pushed the rpc/sendable-subscribable branch from 7333125 to 06be15d Compare June 5, 2026 15:56

@lorisleiva lorisleiva left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the changes!

@mcintyre94 mcintyre94 force-pushed the react/depend-on-kit branch from 183fcb1 to bd5965a Compare June 10, 2026 15:43
@mcintyre94 mcintyre94 force-pushed the rpc/sendable-subscribable branch from 06be15d to 12d6126 Compare June 10, 2026 15:43
@mcintyre94 mcintyre94 force-pushed the react/depend-on-kit branch from bd5965a to e870691 Compare June 10, 2026 16:49
@mcintyre94 mcintyre94 force-pushed the rpc/sendable-subscribable branch from 12d6126 to ec7a400 Compare June 10, 2026 16:49
@mcintyre94 mcintyre94 added the do-not-close Add this tag to exempt an issue/PR from being closed by the stalebot label Jun 11, 2026
inputs

Now takes a `ReactiveActionStore` instead of `PendingRpcRequest`, and
`ReactiveStreamStore` instead of `PendingRpcSubscriptionRequest`
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

do-not-close Add this tag to exempt an issue/PR from being closed by the stalebot

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants