[sync] allow connections from v4 clients (#3173)

See discussion on discord in development channel

### Change Type

<!--  Please select a 'Scope' label ️ -->

- [ ] `sdk` — Changes the tldraw SDK
- [x] `dotcom` — Changes the tldraw.com web app
- [ ] `docs` — Changes to the documentation, examples, or templates.
- [ ] `vs code` — Changes to the vscode plugin
- [ ] `internal` — Does not affect user-facing stuff

<!--  Please select a 'Type' label ️ -->

- [x] `bugfix` — Bug fix
- [ ] `feature` — New feature
- [ ] `improvement` — Improving existing features
- [ ] `chore` — Updating dependencies, other boring stuff
- [ ] `galaxy brain` — Architectural changes
- [ ] `tests` — Changes to any test code
- [ ] `tools` — Changes to infrastructure, CI, internal scripts,
debugging tools, etc.
- [ ] `dunno` — I don't know


### Test Plan

1. Add a step-by-step description of how to test your PR here.
2.

- [ ] Unit Tests
- [ ] End to end tests

### Release Notes

- Add a brief release note for your PR here.
This commit is contained in:
David Sheldrick 2024-03-16 10:21:37 +00:00 committed by GitHub
parent 08e79418f2
commit dc05890407
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
5 changed files with 27 additions and 4 deletions

View file

@ -33,6 +33,7 @@ export type RoomSession<R extends UnknownRecord> =
state: typeof RoomSessionState.Connected
sessionKey: string
presenceId: string
isV4Client: boolean
socket: TLRoomSocket<R>
serializedSchema: SerializedSchema
lastInteractionTime: number

View file

@ -367,6 +367,13 @@ export class TLSyncClient<R extends UnknownRecord, S extends Store<R> = Store<R>
console.error('Restarting socket')
this.socket.restart()
break
// legacy v4 events
case 'patch':
case 'push_result':
if (!this.isConnectedToRoom) break
this.incomingDiffBuffer.push(event)
this.scheduleRebase()
break
case 'data':
// wait for a connect to succeed before processing more events
if (!this.isConnectedToRoom) break

View file

@ -413,7 +413,9 @@ export class TLSyncRoom<R extends UnknownRecord> {
} else {
if (session.debounceTimer === null) {
// this is the first message since the last flush, don't delay it
session.socket.sendMessage({ type: 'data', data: [message] })
session.socket.sendMessage(
session.isV4Client ? message : { type: 'data', data: [message] }
)
session.debounceTimer = setTimeout(
() => this._flushDataMessages(sessionKey),
@ -440,7 +442,14 @@ export class TLSyncRoom<R extends UnknownRecord> {
session.debounceTimer = null
if (session.outstandingDataMessages.length > 0) {
session.socket.sendMessage({ type: 'data', data: session.outstandingDataMessages })
if (session.isV4Client) {
// v4 clients don't support the "data" message, so we need to send each message separately
for (const message of session.outstandingDataMessages) {
session.socket.sendMessage(message)
}
} else {
session.socket.sendMessage({ type: 'data', data: session.outstandingDataMessages })
}
session.outstandingDataMessages.length = 0
}
}
@ -662,7 +671,11 @@ export class TLSyncRoom<R extends UnknownRecord> {
// if the protocol versions don't match, disconnect the client
// we will eventually want to try to make our protocol backwards compatible to some degree
// and have a MIN_PROTOCOL_VERSION constant that the TLSyncRoom implements support for
if (message.protocolVersion == null || message.protocolVersion < TLSYNC_PROTOCOL_VERSION) {
const isV4Client = message.protocolVersion === 4 && TLSYNC_PROTOCOL_VERSION === 5
if (
message.protocolVersion == null ||
(message.protocolVersion < TLSYNC_PROTOCOL_VERSION && !isV4Client)
) {
this.rejectSession(session, TLIncompatibilityReason.ClientTooOld)
return
} else if (message.protocolVersion > TLSYNC_PROTOCOL_VERSION) {
@ -688,6 +701,7 @@ export class TLSyncRoom<R extends UnknownRecord> {
state: RoomSessionState.Connected,
sessionKey: session.sessionKey,
presenceId: session.presenceId,
isV4Client,
socket: session.socket,
serializedSchema: sessionSchema,
lastInteractionTime: Date.now(),

View file

@ -39,6 +39,7 @@ export type TLSocketServerSentEvent<R extends UnknownRecord> =
type: 'pong'
}
| { type: 'data'; data: TLSocketServerSentDataEvent<R>[] }
| TLSocketServerSentDataEvent<R>
/** @public */
export type TLSocketServerSentDataEvent<R extends UnknownRecord> =

View file

@ -362,7 +362,7 @@ test('clients using an out-of-date protocol will receive compatibility errors',
type: 'connect',
connectRequestId: 'test',
lastServerClock: 0,
protocolVersion: TLSYNC_PROTOCOL_VERSION - 1,
protocolVersion: TLSYNC_PROTOCOL_VERSION - 2,
schema: schemaV2.serialize(),
})