@livestore/sync-cf 0.3.0-dev.10 → 0.3.0-dev.12

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1 +1 @@
1
- {"version":3,"file":"ws-impl.js","sourceRoot":"","sources":["../../src/sync-impl/ws-impl.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"ws-impl.js","sourceRoot":"","sources":["../../src/sync-impl/ws-impl.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@livestore/sync-cf",
3
- "version": "0.3.0-dev.10",
3
+ "version": "0.3.0-dev.12",
4
4
  "type": "module",
5
5
  "sideEffects": false,
6
6
  "exports": {
@@ -14,8 +14,8 @@
14
14
  }
15
15
  },
16
16
  "dependencies": {
17
- "@livestore/common": "0.3.0-dev.10",
18
- "@livestore/utils": "0.3.0-dev.10"
17
+ "@livestore/common": "0.3.0-dev.12",
18
+ "@livestore/utils": "0.3.0-dev.12"
19
19
  },
20
20
  "devDependencies": {
21
21
  "@cloudflare/workers-types": "^4.20241022.0"
@@ -1,4 +1,4 @@
1
- import { makeColumnSpec } from '@livestore/common'
1
+ import { makeColumnSpec, UnexpectedError } from '@livestore/common'
2
2
  import { DbSchema, EventId, type MutationEvent } from '@livestore/common/schema'
3
3
  import { shouldNeverHappen } from '@livestore/utils'
4
4
  import { Effect, Logger, LogLevel, Option, Schema } from '@livestore/utils/effect'
@@ -19,8 +19,8 @@ const encodeOutgoingMessage = Schema.encodeSync(Schema.parseJson(WSMessage.Backe
19
19
  const encodeIncomingMessage = Schema.encodeSync(Schema.parseJson(WSMessage.ClientToBackendMessage))
20
20
  const decodeIncomingMessage = Schema.decodeUnknownEither(Schema.parseJson(WSMessage.ClientToBackendMessage))
21
21
 
22
- // NOTE actual table name is determined at runtime by `WebSocketServer.dbName`
23
- export const mutationLogTable = DbSchema.table('__unused', {
22
+ // NOTE actual table name is determined at runtime
23
+ export const mutationLogTable = DbSchema.table('mutation_log_${PERSISTENCE_FORMAT_VERSION}_${storeId}', {
24
24
  id: DbSchema.integer({ primaryKey: true, schema: EventId.GlobalEventId }),
25
25
  parentId: DbSchema.integer({ schema: EventId.GlobalEventId }),
26
26
  mutation: DbSchema.text({}),
@@ -29,6 +29,12 @@ export const mutationLogTable = DbSchema.table('__unused', {
29
29
  createdAt: DbSchema.text({}),
30
30
  })
31
31
 
32
+ const WebSocketAttachmentSchema = Schema.parseJson(
33
+ Schema.Struct({
34
+ storeId: Schema.String,
35
+ }),
36
+ )
37
+
32
38
  /**
33
39
  * Needs to be bumped when the storage format changes (e.g. mutationLogTable schema changes)
34
40
  *
@@ -47,22 +53,20 @@ export type MakeDurableObjectClass = (options?: MakeDurableObjectClassOptions) =
47
53
 
48
54
  export const makeDurableObject: MakeDurableObjectClass = (options) => {
49
55
  return class WebSocketServerBase extends DurableObject<Env> {
50
- storage: SyncStorage | undefined = undefined
51
-
52
56
  constructor(ctx: DurableObjectState, env: Env) {
53
57
  super(ctx, env)
54
58
  }
55
59
 
56
60
  fetch = async (request: Request) =>
57
61
  Effect.gen(this, function* () {
58
- if (this.storage === undefined) {
59
- const storeId = getStoreId(request)
60
- const dbName = `mutation_log_${PERSISTENCE_FORMAT_VERSION}_${toValidTableName(storeId)}`
61
- this.storage = makeStorage(this.ctx, this.env, dbName)
62
- }
62
+ const storeId = getStoreId(request)
63
+ const storage = makeStorage(this.ctx, this.env, storeId)
63
64
 
64
65
  const { 0: client, 1: server } = new WebSocketPair()
65
66
 
67
+ // Since we're using websocket hibernation, we need to remember the storeId for subsequent `webSocketMessage` calls
68
+ server.serializeAttachment(Schema.encodeSync(WebSocketAttachmentSchema)({ storeId }))
69
+
66
70
  // See https://developers.cloudflare.com/durable-objects/examples/websocket-hibernation-server
67
71
 
68
72
  this.ctx.acceptWebSocket(server)
@@ -75,7 +79,7 @@ export const makeDurableObject: MakeDurableObjectClass = (options) => {
75
79
  )
76
80
 
77
81
  const colSpec = makeColumnSpec(mutationLogTable.sqliteDef.ast)
78
- this.env.DB.exec(`CREATE TABLE IF NOT EXISTS ${this.storage.dbName} (${colSpec}) strict`)
82
+ this.env.DB.exec(`CREATE TABLE IF NOT EXISTS ${storage.dbName} (${colSpec}) strict`)
79
83
 
80
84
  return new Response(null, {
81
85
  status: 101,
@@ -92,17 +96,15 @@ export const makeDurableObject: MakeDurableObjectClass = (options) => {
92
96
  return
93
97
  }
94
98
 
99
+ const { storeId } = yield* Schema.decode(WebSocketAttachmentSchema)(ws.deserializeAttachment())
100
+ const storage = makeStorage(this.ctx, this.env, storeId)
101
+
95
102
  const decodedMessage = decodedMessageRes.right
96
103
  const requestId = decodedMessage.requestId
97
104
 
98
- const storage = this.storage
99
-
100
- if (storage === undefined) {
101
- throw new Error('storage not initialized')
102
- }
103
-
104
105
  try {
105
106
  switch (decodedMessage._tag) {
107
+ // TODO allow pulling concurrently to not block incoming push requests
106
108
  case 'WSMessage.PullReq': {
107
109
  if (options?.onPull) {
108
110
  yield* Effect.tryAll(() => options.onPull!(decodedMessage))
@@ -112,21 +114,14 @@ export const makeDurableObject: MakeDurableObjectClass = (options) => {
112
114
  const CHUNK_SIZE = 100
113
115
 
114
116
  // TODO use streaming
115
- const remainingEvents = [...(yield* Effect.promise(() => storage.getEvents(cursor)))]
117
+ const remainingEvents = yield* storage.getEvents(cursor)
116
118
 
117
119
  // NOTE we want to make sure the WS server responds at least once with `InitRes` even if `events` is empty
118
- while (true) {
119
- const events = remainingEvents.splice(0, CHUNK_SIZE)
120
+ for (let i = 0; i < remainingEvents.length; i += CHUNK_SIZE) {
121
+ const batch = remainingEvents.slice(i, i + CHUNK_SIZE)
122
+ const remaining = remainingEvents.length - i - 1
120
123
 
121
- ws.send(
122
- encodeOutgoingMessage(
123
- WSMessage.PullRes.make({ events, remaining: remainingEvents.length, requestId }),
124
- ),
125
- )
126
-
127
- if (remainingEvents.length === 0) {
128
- break
129
- }
124
+ ws.send(encodeOutgoingMessage(WSMessage.PullRes.make({ batch, remaining })))
130
125
  }
131
126
 
132
127
  break
@@ -136,61 +131,63 @@ export const makeDurableObject: MakeDurableObjectClass = (options) => {
136
131
  yield* Effect.tryAll(() => options.onPush!(decodedMessage))
137
132
  }
138
133
 
134
+ if (decodedMessage.batch.length === 0) {
135
+ ws.send(encodeOutgoingMessage(WSMessage.PushAck.make({ requestId })))
136
+ return
137
+ }
138
+
139
139
  // TODO check whether we could use the Durable Object storage for this to speed up the lookup
140
- const latestEvent = yield* Effect.promise(() => storage.getLatestEvent())
141
- const expectedParentId = latestEvent?.id ?? EventId.ROOT.global
140
+ const expectedParentId = yield* storage.getHead
142
141
 
143
- let i = 0
144
- for (const mutationEventEncoded of decodedMessage.batch) {
145
- if (mutationEventEncoded.parentId !== expectedParentId + i) {
146
- const err = WSMessage.Error.make({
147
- message: `Invalid parent id. Received ${mutationEventEncoded.parentId} but expected ${expectedParentId}`,
148
- requestId,
149
- })
142
+ // TODO handle clientId unique conflict
150
143
 
151
- yield* Effect.fail(err).pipe(Effect.ignoreLogged)
144
+ // Validate the batch
145
+ const firstEvent = decodedMessage.batch[0]!
146
+ if (firstEvent.parentId !== expectedParentId) {
147
+ const err = WSMessage.Error.make({
148
+ message: `Invalid parent id. Received ${firstEvent.parentId} but expected ${expectedParentId}`,
149
+ requestId,
150
+ })
152
151
 
153
- ws.send(encodeOutgoingMessage(err))
154
- return
155
- }
152
+ yield* Effect.logError(err)
156
153
 
157
- // TODO handle clientId unique conflict
154
+ ws.send(encodeOutgoingMessage(err))
155
+ return
156
+ }
158
157
 
159
- const createdAt = new Date().toISOString()
158
+ ws.send(encodeOutgoingMessage(WSMessage.PushAck.make({ requestId })))
160
159
 
161
- // NOTE we're currently not blocking on this to allow broadcasting right away
162
- const storePromise = storage.appendEvent(mutationEventEncoded, createdAt)
160
+ const createdAt = new Date().toISOString()
163
161
 
164
- ws.send(
165
- encodeOutgoingMessage(WSMessage.PushAck.make({ mutationId: mutationEventEncoded.id, requestId })),
166
- )
162
+ // NOTE we're not waiting for this to complete yet to allow the broadcast to happen right away
163
+ // while letting the async storage write happen in the background
164
+ const storeFiber = yield* storage.appendEvents(decodedMessage.batch, createdAt).pipe(Effect.fork)
167
165
 
168
- // console.debug(`Broadcasting mutation event to ${this.subscribedWebSockets.size} clients`)
166
+ const connectedClients = this.ctx.getWebSockets()
169
167
 
170
- const connectedClients = this.ctx.getWebSockets()
168
+ // console.debug(`Broadcasting push batch to ${this.subscribedWebSockets.size} clients`)
171
169
 
172
- if (connectedClients.length > 0) {
173
- const broadcastMessage = encodeOutgoingMessage(
174
- // TODO refactor to batch api
175
- WSMessage.PushBroadcast.make({
170
+ if (connectedClients.length > 0) {
171
+ const pullRes = encodeOutgoingMessage(
172
+ // TODO refactor to batch api
173
+ WSMessage.PullRes.make({
174
+ batch: decodedMessage.batch.map((mutationEventEncoded) => ({
176
175
  mutationEventEncoded,
177
176
  metadata: Option.some({ createdAt }),
178
- }),
179
- )
180
-
181
- for (const conn of connectedClients) {
182
- console.log('Broadcasting to client', conn === ws ? 'self' : 'other')
183
- // if (conn !== ws) {
184
- conn.send(broadcastMessage)
185
- // }
186
- }
187
- }
188
-
189
- yield* Effect.promise(() => storePromise)
177
+ })),
178
+ remaining: 0,
179
+ }),
180
+ )
190
181
 
191
- i++
182
+ // NOTE we're also sending the pullRes to the pushing ws client as a confirmation
183
+ for (const conn of connectedClients) {
184
+ conn.send(pullRes)
185
+ }
192
186
  }
193
187
 
188
+ // Wait for the storage write to complete before finishing this request
189
+ yield* storeFiber
190
+
194
191
  break
195
192
  }
196
193
  case 'WSMessage.AdminResetRoomReq': {
@@ -199,7 +196,7 @@ export const makeDurableObject: MakeDurableObjectClass = (options) => {
199
196
  return
200
197
  }
201
198
 
202
- yield* Effect.promise(() => storage.resetRoom())
199
+ yield* storage.resetStore
203
200
  ws.send(encodeOutgoingMessage(WSMessage.AdminResetRoomRes.make({ requestId })))
204
201
 
205
202
  break
@@ -243,60 +240,96 @@ export const makeDurableObject: MakeDurableObjectClass = (options) => {
243
240
 
244
241
  type SyncStorage = {
245
242
  dbName: string
246
- getLatestEvent: () => Promise<MutationEvent.AnyEncodedGlobal | undefined>
243
+ getHead: Effect.Effect<EventId.GlobalEventId, UnexpectedError>
247
244
  getEvents: (
248
245
  cursor: number | undefined,
249
- ) => Promise<
250
- ReadonlyArray<{ mutationEventEncoded: MutationEvent.AnyEncodedGlobal; metadata: Option.Option<SyncMetadata> }>
246
+ ) => Effect.Effect<
247
+ ReadonlyArray<{ mutationEventEncoded: MutationEvent.AnyEncodedGlobal; metadata: Option.Option<SyncMetadata> }>,
248
+ UnexpectedError
251
249
  >
252
- appendEvent: (event: MutationEvent.AnyEncodedGlobal, createdAt: string) => Promise<void>
253
- resetRoom: () => Promise<void>
250
+ appendEvents: (
251
+ batch: ReadonlyArray<MutationEvent.AnyEncodedGlobal>,
252
+ createdAt: string,
253
+ ) => Effect.Effect<void, UnexpectedError>
254
+ resetStore: Effect.Effect<void, UnexpectedError>
254
255
  }
255
256
 
256
- const makeStorage = (ctx: DurableObjectState, env: Env, dbName: string): SyncStorage => {
257
- const getLatestEvent = async (): Promise<MutationEvent.AnyEncodedGlobal | undefined> => {
258
- const rawEvents = await env.DB.prepare(`SELECT * FROM ${dbName} ORDER BY id DESC LIMIT 1`).all()
259
- if (rawEvents.error) {
260
- throw new Error(rawEvents.error)
261
- }
262
- const events = Schema.decodeUnknownSync(Schema.Array(mutationLogTable.schema))(rawEvents.results)
257
+ const makeStorage = (ctx: DurableObjectState, env: Env, storeId: string): SyncStorage => {
258
+ const dbName = `mutation_log_${PERSISTENCE_FORMAT_VERSION}_${toValidTableName(storeId)}`
263
259
 
264
- return events[0]
265
- }
260
+ const execDb = <T>(cb: (db: D1Database) => Promise<D1Result<T>>) =>
261
+ Effect.tryPromise({
262
+ try: () => cb(env.DB),
263
+ catch: (error) => new UnexpectedError({ cause: error, payload: { dbName } }),
264
+ }).pipe(Effect.map((_) => _.results))
266
265
 
267
- const getEvents = async (
268
- cursor: number | undefined,
269
- ): Promise<
270
- ReadonlyArray<{ mutationEventEncoded: MutationEvent.AnyEncodedGlobal; metadata: Option.Option<SyncMetadata> }>
271
- > => {
272
- const whereClause = cursor === undefined ? '' : `WHERE id > ${cursor}`
273
- const sql = `SELECT * FROM ${dbName} ${whereClause} ORDER BY id ASC`
274
- // TODO handle case where `cursor` was not found
275
- const rawEvents = await env.DB.prepare(sql).all()
276
- if (rawEvents.error) {
277
- throw new Error(rawEvents.error)
278
- }
279
- const events = Schema.decodeUnknownSync(Schema.Array(mutationLogTable.schema))(rawEvents.results).map(
280
- ({ createdAt, ...mutationEventEncoded }) => ({
281
- mutationEventEncoded,
282
- metadata: Option.some({ createdAt }),
283
- }),
266
+ const getHead: Effect.Effect<EventId.GlobalEventId, UnexpectedError> = Effect.gen(function* () {
267
+ const result = yield* execDb<{ id: EventId.GlobalEventId }>((db) =>
268
+ db.prepare(`SELECT id FROM ${dbName} ORDER BY id DESC LIMIT 1`).all(),
284
269
  )
285
- return events
286
- }
287
270
 
288
- const appendEvent = async (event: MutationEvent.AnyEncodedGlobal, createdAt: string) => {
289
- const sql = `INSERT INTO ${dbName} (id, parentId, args, mutation, createdAt) VALUES (?, ?, ?, ?, ?)`
290
- await env.DB.prepare(sql)
291
- .bind(event.id, event.parentId, JSON.stringify(event.args), event.mutation, createdAt)
292
- .run()
293
- }
271
+ return result[0]?.id ?? EventId.ROOT.global
272
+ }).pipe(UnexpectedError.mapToUnexpectedError)
294
273
 
295
- const resetRoom = async () => {
296
- await ctx.storage.deleteAll()
297
- }
274
+ const getEvents = (
275
+ cursor: number | undefined,
276
+ ): Effect.Effect<
277
+ ReadonlyArray<{ mutationEventEncoded: MutationEvent.AnyEncodedGlobal; metadata: Option.Option<SyncMetadata> }>,
278
+ UnexpectedError
279
+ > =>
280
+ Effect.gen(function* () {
281
+ const whereClause = cursor === undefined ? '' : `WHERE id > ${cursor}`
282
+ const sql = `SELECT * FROM ${dbName} ${whereClause} ORDER BY id ASC`
283
+ // TODO handle case where `cursor` was not found
284
+ const rawEvents = yield* execDb((db) => db.prepare(sql).all())
285
+ const events = Schema.decodeUnknownSync(Schema.Array(mutationLogTable.schema))(rawEvents).map(
286
+ ({ createdAt, ...mutationEventEncoded }) => ({
287
+ mutationEventEncoded,
288
+ metadata: Option.some({ createdAt }),
289
+ }),
290
+ )
291
+ return events
292
+ })
293
+
294
+ const appendEvents: SyncStorage['appendEvents'] = (batch, createdAt) =>
295
+ Effect.gen(function* () {
296
+ // If there are no events, do nothing.
297
+ if (batch.length === 0) return
298
+
299
+ // CF D1 limits:
300
+ // Maximum bound parameters per query 100, Maximum arguments per SQL function 32
301
+ // Thus we need to split the batch into chunks of max (100/5=)20 events each.
302
+ const CHUNK_SIZE = 20
303
+
304
+ for (let i = 0; i < batch.length; i += CHUNK_SIZE) {
305
+ const chunk = batch.slice(i, i + CHUNK_SIZE)
306
+
307
+ // Create a list of placeholders ("(?, ?, ?, ?, ?), …") corresponding to each event.
308
+ const valuesPlaceholders = chunk.map(() => '(?, ?, ?, ?, ?)').join(', ')
309
+ const sql = `INSERT INTO ${dbName} (id, parentId, args, mutation, createdAt) VALUES ${valuesPlaceholders}`
310
+ // Flatten the event properties into a parameters array.
311
+ const params = chunk.flatMap((event) => [
312
+ event.id,
313
+ event.parentId,
314
+ JSON.stringify(event.args),
315
+ event.mutation,
316
+ createdAt,
317
+ ])
318
+
319
+ yield* execDb((db) =>
320
+ db
321
+ .prepare(sql)
322
+ .bind(...params)
323
+ .run(),
324
+ )
325
+ }
326
+ })
327
+
328
+ const resetStore = Effect.gen(function* () {
329
+ yield* Effect.promise(() => ctx.storage.deleteAll())
330
+ }).pipe(UnexpectedError.mapToUnexpectedError)
298
331
 
299
- return { dbName, getLatestEvent, getEvents, appendEvent, resetRoom }
332
+ return { dbName, getHead, getEvents, appendEvents, resetStore }
300
333
  }
301
334
 
302
335
  const getStoreId = (request: Request) => {
@@ -17,8 +17,7 @@ export const SyncMetadata = Schema.Struct({
17
17
  export type SyncMetadata = typeof SyncMetadata.Type
18
18
 
19
19
  export const PullRes = Schema.TaggedStruct('WSMessage.PullRes', {
20
- requestId: Schema.String,
21
- events: Schema.Array(
20
+ batch: Schema.Array(
22
21
  Schema.Struct({
23
22
  mutationEventEncoded: MutationEvent.AnyEncodedGlobal,
24
23
  metadata: Schema.Option(SyncMetadata),
@@ -29,13 +28,6 @@ export const PullRes = Schema.TaggedStruct('WSMessage.PullRes', {
29
28
 
30
29
  export type PullRes = typeof PullRes.Type
31
30
 
32
- export const PushBroadcast = Schema.TaggedStruct('WSMessage.PushBroadcast', {
33
- mutationEventEncoded: MutationEvent.AnyEncodedGlobal,
34
- metadata: Schema.Option(SyncMetadata),
35
- })
36
-
37
- export type PushBroadcast = typeof PushBroadcast.Type
38
-
39
31
  export const PushReq = Schema.TaggedStruct('WSMessage.PushReq', {
40
32
  requestId: Schema.String,
41
33
  batch: Schema.Array(MutationEvent.AnyEncodedGlobal),
@@ -45,7 +37,6 @@ export type PushReq = typeof PushReq.Type
45
37
 
46
38
  export const PushAck = Schema.TaggedStruct('WSMessage.PushAck', {
47
39
  requestId: Schema.String,
48
- mutationId: Schema.Number,
49
40
  })
50
41
 
51
42
  export type PushAck = typeof PushAck.Type
@@ -99,7 +90,6 @@ export type AdminInfoRes = typeof AdminInfoRes.Type
99
90
  export const Message = Schema.Union(
100
91
  PullReq,
101
92
  PullRes,
102
- PushBroadcast,
103
93
  PushReq,
104
94
  PushAck,
105
95
  Error,
@@ -113,15 +103,7 @@ export const Message = Schema.Union(
113
103
  export type Message = typeof Message.Type
114
104
  export type MessageEncoded = typeof Message.Encoded
115
105
 
116
- export const BackendToClientMessage = Schema.Union(
117
- PullRes,
118
- PushBroadcast,
119
- PushAck,
120
- AdminResetRoomRes,
121
- AdminInfoRes,
122
- Error,
123
- Pong,
124
- )
106
+ export const BackendToClientMessage = Schema.Union(PullRes, PushAck, AdminResetRoomRes, AdminInfoRes, Error, Pong)
125
107
  export type BackendToClientMessage = typeof BackendToClientMessage.Type
126
108
 
127
109
  export const ClientToBackendMessage = Schema.Union(PullReq, PushReq, AdminResetRoomReq, AdminInfoReq, Ping)
@@ -2,7 +2,7 @@
2
2
 
3
3
  import type { SyncBackend } from '@livestore/common'
4
4
  import { InvalidPullError, InvalidPushError } from '@livestore/common'
5
- import { pick } from '@livestore/utils'
5
+ import { LS_DEV } from '@livestore/utils'
6
6
  import type { Scope } from '@livestore/utils/effect'
7
7
  import {
8
8
  Deferred,
@@ -43,24 +43,13 @@ export const makeWsSync = (options: WsSyncOptions): Effect.Effect<SyncBackend<Sy
43
43
  yield* send(WSMessage.PullReq.make({ cursor, requestId }))
44
44
 
45
45
  return Stream.fromPubSub(incomingMessages).pipe(
46
- Stream.filter((_) => (_._tag === 'WSMessage.PullRes' ? _.requestId === requestId : true)),
47
46
  Stream.tap((_) =>
48
47
  _._tag === 'WSMessage.Error' && _.requestId === requestId
49
48
  ? new InvalidPullError({ message: _.message })
50
49
  : Effect.void,
51
50
  ),
52
- Stream.filter(Schema.is(Schema.Union(WSMessage.PushBroadcast, WSMessage.PullRes))),
53
- Stream.map((msg) =>
54
- msg._tag === 'WSMessage.PushBroadcast'
55
- ? { batch: [pick(msg, ['mutationEventEncoded', 'metadata'])], remaining: 0 }
56
- : {
57
- batch: msg.events.map(({ mutationEventEncoded, metadata }) => ({
58
- mutationEventEncoded,
59
- metadata,
60
- })),
61
- remaining: msg.remaining,
62
- },
63
- ),
51
+ // This call is mostly here to for type narrowing
52
+ Stream.filter(Schema.is(WSMessage.PullRes)),
64
53
  )
65
54
  }).pipe(Stream.unwrap),
66
55
 
@@ -70,15 +59,12 @@ export const makeWsSync = (options: WsSyncOptions): Effect.Effect<SyncBackend<Sy
70
59
  const requestId = nanoid()
71
60
 
72
61
  yield* Stream.fromPubSub(incomingMessages).pipe(
73
- Stream.filter((_) => _._tag !== 'WSMessage.PushBroadcast' && _.requestId === requestId),
74
62
  Stream.tap((_) =>
75
- _._tag === 'WSMessage.Error'
63
+ _._tag === 'WSMessage.Error' && _.requestId === requestId
76
64
  ? Deferred.fail(ready, new InvalidPushError({ reason: { _tag: 'Unexpected', message: _.message } }))
77
65
  : Effect.void,
78
66
  ),
79
- Stream.filter(Schema.is(WSMessage.PushAck)),
80
- // TODO bring back filterting of "own events"
81
- // Stream.filter((_) => _.mutationId === mutationEventEncoded.id.global),
67
+ Stream.filter((_) => _._tag === 'WSMessage.PushAck' && _.requestId === requestId),
82
68
  Stream.take(1),
83
69
  Stream.tap(() => Deferred.succeed(ready, void 0)),
84
70
  Stream.runDrain,
@@ -115,21 +101,23 @@ const connect = (wsUrl: string) =>
115
101
  // Wait first until we're online
116
102
  yield* waitUntilOnline
117
103
 
118
- yield* Effect.spanEvent(
119
- `Sending message: ${message._tag}`,
120
- message._tag === 'WSMessage.PushReq'
121
- ? {
122
- id: message.batch[0]!.id,
123
- parentId: message.batch[0]!.parentId,
124
- batchLength: message.batch.length,
125
- }
126
- : message._tag === 'WSMessage.PullReq'
127
- ? { cursor: message.cursor ?? '-' }
128
- : {},
129
- )
130
-
131
104
  // TODO use MsgPack instead of JSON to speed up the serialization / reduce the size of the messages
132
105
  socketRef.current!.send(Schema.encodeSync(Schema.parseJson(WSMessage.Message))(message))
106
+
107
+ if (LS_DEV) {
108
+ yield* Effect.spanEvent(
109
+ `Sent message: ${message._tag}`,
110
+ message._tag === 'WSMessage.PushReq'
111
+ ? {
112
+ id: message.batch[0]!.id,
113
+ parentId: message.batch[0]!.parentId,
114
+ batchLength: message.batch.length,
115
+ }
116
+ : message._tag === 'WSMessage.PullReq'
117
+ ? { cursor: message.cursor ?? '-' }
118
+ : {},
119
+ )
120
+ }
133
121
  })
134
122
 
135
123
  const innerConnect = Effect.gen(function* () {
@@ -138,6 +126,7 @@ const connect = (wsUrl: string) =>
138
126
  while (typeof navigator !== 'undefined' && navigator.onLine === false) {
139
127
  yield* Effect.sleep(1000)
140
128
  }
129
+ // TODO bring this back in a cross-platform way
141
130
  // if (navigator.onLine === false) {
142
131
  // yield* Effect.async((cb) => self.addEventListener('online', () => cb(Effect.void)))
143
132
  // }