Repository navigation
Commit d5c970e
authored
feat(client): duplex stream channels with a send path (#107)
* feat(client-core): let a subscription speak first, and again after a reconnect
subscribe() takes hello and goodbye frames. hello goes out once the
transport reports open and after every reconnect, in subscription
order; goodbye goes out on release while the socket is up. A transport
without send() refuses a hello at subscribe time rather than dropping
it. The snapshot says which channels carry a hello, and attempts may be
Infinity, which the reconnect loop already honoured.
* fix(client-core): send hello once, order onReconnect after greet, guard goodbye-only
Three defects from review. First, a first subscribe on a transport
with no onOpen greeted the new hello inside open() and then sent it
again in subscribe() itself; subscribe() now skips the explicit send
when this call is the one that opened the socket. Second, onReconnect
fired right after open() returned even on a transport whose open event
has not happened yet, so a consumer refetching on reconnect could run
before the hello reintroducing the subscription went out; open() now
takes the reconnect's channel list and reports it from the ready path,
after greet(), never before. Third, the no-send guard only checked
hello, so a goodbye-only subscription on a connection without send()
returned normally and later dropped its goodbye in silence; the guard
now applies whenever either option is present.
Updated the gap-recovery and reconnect tests that relied on the old,
premature onReconnect timing to call open() on the reconnected fake
connection, matching what a real transport requires before the manager
can call it ready.
* fix(client-core): carry hello/goodbye through a repartition reopen too
repartition() had the same two defects reconnect() just had fixed.
It called onReconnect right after open(), before the replacement
socket's transport had actually reported open, so a consumer acting
on onReconnect could run before the replacement was greeted. And it
copied channels and refs onto the replacement socket but never
frames, so every surviving subscription's hello and goodbye
registration was silently dropped on an identity change: no hello
went out on the reopened socket and the server never learned the
subscription existed again.
frames now carries over in the same insertion order, and repartition
routes its onReconnect through open()'s report parameter, so it fires
from the ready path after greet(), exactly like a drop-triggered
reconnect.
* feat(client-core): a duplex binding kind the binder hands over raw
StreamBinding is now a union: the entity binding everyone generates
today, with an optional kind, and a duplex binding for a channel the
client speaks on with no entity behind it. The binder keeps duplex
channels out of the entity store and exposes raw(channel, handler,
options), which subscribes through the manager with hello and goodbye
frames and refuses any channel the generated table does not declare.
Three existing tests read StreamBinding fields the brief did not list:
frame-ordering.test.ts and overlay.test.ts built entity bindings typed
as the bare union and passed them to a frame() helper typed the same
way, and live.test.ts read .message off a ChannelBindings.bindings
array. All three are narrowed to EntityStreamBinding, the first two by
retyping the fixtures and the helper, the last with an isDuplex filter,
rather than cast.
stream binding measured 4040 B against its 3.75 kB budget once raw()
and isDuplex landed. Raised to 4.2 kB, which clears the measurement
with about the same headroom the query engine's own budget carries.
* feat(client-gen): emit a duplex binding for a send-and-receive channel
A WebSocket channel that declares both a send and a receive operation
and no entity is one the client speaks on; the binder takes its frames
raw. writeStreams now emits it with kind 'duplex' and the two message
names, and stamps kind 'entity' on the bindings it already emitted.
The kind is optional on entity bindings in client-core, so every table
generated before this keeps type-checking.
* fix(client-devtools): render duplex stream bindings in the streams tab
The bindings table read message, entity, intent and invalidates off every
binding. With StreamBinding now a union that no longer compiles, and at
runtime the first duplex binding threw and blanked the whole tab. The table
narrows on kind: an entity row keeps its columns and a duplex row shows the
send and receive message names with the entity columns empty.
The socket snapshot rows now carry hello, so the live-panel test expects
it, and the streams test narrows its binding assertion for the union.1 parent d96026c commit d5c970e
17 files changed
Lines changed: 731 additions & 50 deletions
File tree
- internal/client/generators/typescript
- packages
- client-core
- __tests__
- src
- client-devtools
- __tests__
- src
Lines changed: 65 additions & 0 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
145 | 145 | | |
146 | 146 | | |
147 | 147 | | |
| 148 | + | |
| 149 | + | |
| 150 | + | |
| 151 | + | |
| 152 | + | |
| 153 | + | |
| 154 | + | |
| 155 | + | |
| 156 | + | |
| 157 | + | |
| 158 | + | |
| 159 | + | |
| 160 | + | |
| 161 | + | |
| 162 | + | |
| 163 | + | |
| 164 | + | |
| 165 | + | |
| 166 | + | |
| 167 | + | |
| 168 | + | |
| 169 | + | |
| 170 | + | |
| 171 | + | |
| 172 | + | |
| 173 | + | |
| 174 | + | |
| 175 | + | |
| 176 | + | |
| 177 | + | |
| 178 | + | |
| 179 | + | |
| 180 | + | |
| 181 | + | |
| 182 | + | |
| 183 | + | |
| 184 | + | |
| 185 | + | |
| 186 | + | |
| 187 | + | |
| 188 | + | |
| 189 | + | |
| 190 | + | |
| 191 | + | |
| 192 | + | |
| 193 | + | |
| 194 | + | |
| 195 | + | |
| 196 | + | |
| 197 | + | |
| 198 | + | |
| 199 | + | |
| 200 | + | |
| 201 | + | |
| 202 | + | |
| 203 | + | |
| 204 | + | |
| 205 | + | |
| 206 | + | |
| 207 | + | |
| 208 | + | |
| 209 | + | |
| 210 | + | |
| 211 | + | |
| 212 | + | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
680 | 680 | | |
681 | 681 | | |
682 | 682 | | |
| 683 | + | |
| 684 | + | |
| 685 | + | |
| 686 | + | |
| 687 | + | |
| 688 | + | |
683 | 689 | | |
| 690 | + | |
684 | 691 | | |
685 | 692 | | |
686 | | - | |
687 | | - | |
| 693 | + | |
| 694 | + | |
| 695 | + | |
| 696 | + | |
| 697 | + | |
| 698 | + | |
688 | 699 | | |
| 700 | + | |
| 701 | + | |
| 702 | + | |
| 703 | + | |
| 704 | + | |
| 705 | + | |
| 706 | + | |
689 | 707 | | |
690 | 708 | | |
691 | 709 | | |
| |||
695 | 713 | | |
696 | 714 | | |
697 | 715 | | |
| 716 | + | |
698 | 717 | | |
699 | 718 | | |
700 | 719 | | |
701 | 720 | | |
702 | 721 | | |
703 | 722 | | |
| 723 | + | |
704 | 724 | | |
705 | 725 | | |
706 | 726 | | |
| |||
710 | 730 | | |
711 | 731 | | |
712 | 732 | | |
| 733 | + | |
| 734 | + | |
| 735 | + | |
| 736 | + | |
| 737 | + | |
| 738 | + | |
| 739 | + | |
| 740 | + | |
| 741 | + | |
| 742 | + | |
| 743 | + | |
| 744 | + | |
713 | 745 | | |
714 | 746 | | |
715 | 747 | | |
| 748 | + | |
| 749 | + | |
| 750 | + | |
| 751 | + | |
| 752 | + | |
| 753 | + | |
| 754 | + | |
| 755 | + | |
| 756 | + | |
| 757 | + | |
| 758 | + | |
| 759 | + | |
| 760 | + | |
| 761 | + | |
| 762 | + | |
| 763 | + | |
| 764 | + | |
| 765 | + | |
| 766 | + | |
| 767 | + | |
| 768 | + | |
| 769 | + | |
| 770 | + | |
716 | 771 | | |
717 | 772 | | |
718 | 773 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
| 11 | + | |
| 12 | + | |
| 13 | + | |
| 14 | + | |
| 15 | + | |
| 16 | + | |
| 17 | + | |
| 18 | + | |
| 19 | + | |
| 20 | + | |
| 21 | + | |
| 22 | + | |
| 23 | + | |
| 24 | + | |
| 25 | + | |
| 26 | + | |
| 27 | + | |
| 28 | + | |
| 29 | + | |
| 30 | + | |
| 31 | + | |
| 32 | + | |
| 33 | + | |
| 34 | + | |
| 35 | + | |
| 36 | + | |
| 37 | + | |
| 38 | + | |
| 39 | + | |
| 40 | + | |
| 41 | + | |
| 42 | + | |
| 43 | + | |
| 44 | + | |
| 45 | + | |
| 46 | + | |
| 47 | + | |
| 48 | + | |
| 49 | + | |
| 50 | + | |
| 51 | + | |
| 52 | + | |
| 53 | + | |
| 54 | + | |
| 55 | + | |
| 56 | + | |
| 57 | + | |
| 58 | + | |
| 59 | + | |
| 60 | + | |
| 61 | + | |
| 62 | + | |
| 63 | + | |
| 64 | + | |
| 65 | + | |
| 66 | + | |
| 67 | + | |
| 68 | + | |
| 69 | + | |
| 70 | + | |
| 71 | + | |
| 72 | + | |
| 73 | + | |
| 74 | + | |
| 75 | + | |
| 76 | + | |
| 77 | + | |
| 78 | + | |
| 79 | + | |
| 80 | + | |
0 commit comments