Simplify tlsync types (#3139)
Replace enums with (const) object types. Was supposed to include https://github.com/tldraw/tldraw/pull/3144, but had to bail out ### Change Type <!-- ❗ Please select a 'Scope' label ❗️ --> - [ ] `sdk` — Changes the tldraw SDK - [ ] `dotcom` — Changes the tldraw.com web app - [ ] `docs` — Changes to the documentation, examples, or templates. - [ ] `vs code` — Changes to the vscode plugin - [x] `internal` — Does not affect user-facing stuff <!-- ❗ Please select a 'Type' label ❗️ --> - [ ] `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. - [x] `dunno` — I don't know
This commit is contained in:
parent
3767a68f0f
commit
a933aaf619
5 changed files with 59 additions and 48 deletions
|
@ -2,11 +2,13 @@ import { SerializedSchema, UnknownRecord } from '@tldraw/store'
|
|||
import { TLRoomSocket } from './TLSyncRoom'
|
||||
import { TLSocketServerSentDataEvent } from './protocol'
|
||||
|
||||
export enum RoomSessionState {
|
||||
AWAITING_CONNECT_MESSAGE = 'awaiting-connect-message',
|
||||
AWAITING_REMOVAL = 'awaiting-removal',
|
||||
CONNECTED = 'connected',
|
||||
}
|
||||
export const RoomSessionState = {
|
||||
AwaitingConnectMessage: 'awaiting-connect-message',
|
||||
AwaitingRemoval: 'awaiting-removal',
|
||||
Connected: 'connected',
|
||||
} as const
|
||||
|
||||
export type RoomSessionState = (typeof RoomSessionState)[keyof typeof RoomSessionState]
|
||||
|
||||
export const SESSION_START_WAIT_TIME = 10000
|
||||
export const SESSION_REMOVAL_WAIT_TIME = 10000
|
||||
|
@ -14,21 +16,21 @@ export const SESSION_IDLE_TIMEOUT = 20000
|
|||
|
||||
export type RoomSession<R extends UnknownRecord> =
|
||||
| {
|
||||
state: RoomSessionState.AWAITING_CONNECT_MESSAGE
|
||||
state: typeof RoomSessionState.AwaitingConnectMessage
|
||||
sessionKey: string
|
||||
presenceId: string
|
||||
socket: TLRoomSocket<R>
|
||||
sessionStartTime: number
|
||||
}
|
||||
| {
|
||||
state: RoomSessionState.AWAITING_REMOVAL
|
||||
state: typeof RoomSessionState.AwaitingRemoval
|
||||
sessionKey: string
|
||||
presenceId: string
|
||||
socket: TLRoomSocket<R>
|
||||
cancellationTime: number
|
||||
}
|
||||
| {
|
||||
state: RoomSessionState.CONNECTED
|
||||
state: typeof RoomSessionState.Connected
|
||||
sessionKey: string
|
||||
presenceId: string
|
||||
socket: TLRoomSocket<R>
|
||||
|
|
|
@ -140,14 +140,14 @@ export class TLSyncRoom<R extends UnknownRecord> {
|
|||
pruneSessions = () => {
|
||||
for (const client of this.sessions.values()) {
|
||||
switch (client.state) {
|
||||
case RoomSessionState.CONNECTED: {
|
||||
case RoomSessionState.Connected: {
|
||||
const hasTimedOut = timeSince(client.lastInteractionTime) > SESSION_IDLE_TIMEOUT
|
||||
if (hasTimedOut || !client.socket.isOpen) {
|
||||
this.cancelSession(client.sessionKey)
|
||||
}
|
||||
break
|
||||
}
|
||||
case RoomSessionState.AWAITING_CONNECT_MESSAGE: {
|
||||
case RoomSessionState.AwaitingConnectMessage: {
|
||||
const hasTimedOut = timeSince(client.sessionStartTime) > SESSION_START_WAIT_TIME
|
||||
if (hasTimedOut || !client.socket.isOpen) {
|
||||
// remove immediately
|
||||
|
@ -155,7 +155,7 @@ export class TLSyncRoom<R extends UnknownRecord> {
|
|||
}
|
||||
break
|
||||
}
|
||||
case RoomSessionState.AWAITING_REMOVAL: {
|
||||
case RoomSessionState.AwaitingRemoval: {
|
||||
const hasTimedOut = timeSince(client.cancellationTime) > SESSION_REMOVAL_WAIT_TIME
|
||||
if (hasTimedOut) {
|
||||
this.removeSession(client.sessionKey)
|
||||
|
@ -397,7 +397,7 @@ export class TLSyncRoom<R extends UnknownRecord> {
|
|||
console.warn('Tried to send message to unknown session', message.type)
|
||||
return
|
||||
}
|
||||
if (session.state !== RoomSessionState.CONNECTED) {
|
||||
if (session.state !== RoomSessionState.Connected) {
|
||||
console.warn('Tried to send message to disconnected client', message.type)
|
||||
return
|
||||
}
|
||||
|
@ -433,7 +433,7 @@ export class TLSyncRoom<R extends UnknownRecord> {
|
|||
_flushDataMessages(sessionKey: string) {
|
||||
const session = this.sessions.get(sessionKey)
|
||||
|
||||
if (!session || session.state !== RoomSessionState.CONNECTED) {
|
||||
if (!session || session.state !== RoomSessionState.Connected) {
|
||||
return
|
||||
}
|
||||
|
||||
|
@ -489,13 +489,13 @@ export class TLSyncRoom<R extends UnknownRecord> {
|
|||
return
|
||||
}
|
||||
|
||||
if (session.state === RoomSessionState.AWAITING_REMOVAL) {
|
||||
if (session.state === RoomSessionState.AwaitingRemoval) {
|
||||
console.warn('Tried to cancel session that is already awaiting removal')
|
||||
return
|
||||
}
|
||||
|
||||
this.sessions.set(sessionKey, {
|
||||
state: RoomSessionState.AWAITING_REMOVAL,
|
||||
state: RoomSessionState.AwaitingRemoval,
|
||||
sessionKey,
|
||||
presenceId: session.presenceId,
|
||||
socket: session.socket,
|
||||
|
@ -517,7 +517,7 @@ export class TLSyncRoom<R extends UnknownRecord> {
|
|||
sourceSessionKey: string
|
||||
}) {
|
||||
this.sessions.forEach((session) => {
|
||||
if (session.state !== RoomSessionState.CONNECTED) return
|
||||
if (session.state !== RoomSessionState.Connected) return
|
||||
if (sourceSessionKey === session.sessionKey) return
|
||||
if (!session.socket.isOpen) {
|
||||
this.cancelSession(session.sessionKey)
|
||||
|
@ -556,7 +556,7 @@ export class TLSyncRoom<R extends UnknownRecord> {
|
|||
handleNewSession = (sessionKey: string, socket: TLRoomSocket<R>) => {
|
||||
const existing = this.sessions.get(sessionKey)
|
||||
this.sessions.set(sessionKey, {
|
||||
state: RoomSessionState.AWAITING_CONNECT_MESSAGE,
|
||||
state: RoomSessionState.AwaitingConnectMessage,
|
||||
sessionKey,
|
||||
socket,
|
||||
presenceId: existing?.presenceId ?? this.presenceType.createId(),
|
||||
|
@ -628,7 +628,7 @@ export class TLSyncRoom<R extends UnknownRecord> {
|
|||
return this.handlePushRequest(session, message)
|
||||
}
|
||||
case 'ping': {
|
||||
if (session.state === RoomSessionState.CONNECTED) {
|
||||
if (session.state === RoomSessionState.Connected) {
|
||||
session.lastInteractionTime = Date.now()
|
||||
}
|
||||
return this.sendMessage(session.sessionKey, { type: 'pong' })
|
||||
|
@ -685,7 +685,7 @@ export class TLSyncRoom<R extends UnknownRecord> {
|
|||
|
||||
const connect = (msg: TLSocketServerSentEvent<R>) => {
|
||||
this.sessions.set(session.sessionKey, {
|
||||
state: RoomSessionState.CONNECTED,
|
||||
state: RoomSessionState.Connected,
|
||||
sessionKey: session.sessionKey,
|
||||
presenceId: session.presenceId,
|
||||
socket: session.socket,
|
||||
|
@ -786,7 +786,7 @@ export class TLSyncRoom<R extends UnknownRecord> {
|
|||
message: Extract<TLSocketClientSentEvent<R>, { type: 'push' }>
|
||||
) {
|
||||
// We must be connected to handle push requests
|
||||
if (session.state !== RoomSessionState.CONNECTED) {
|
||||
if (session.state !== RoomSessionState.Connected) {
|
||||
return
|
||||
}
|
||||
|
||||
|
|
|
@ -3,17 +3,20 @@ import { objectMapEntries, objectMapValues } from '@tldraw/utils'
|
|||
import isEqual from 'lodash.isequal'
|
||||
|
||||
/** @public */
|
||||
export enum RecordOpType {
|
||||
Put = 'put',
|
||||
Patch = 'patch',
|
||||
Remove = 'remove',
|
||||
}
|
||||
export const RecordOpType = {
|
||||
Put: 'put',
|
||||
Patch: 'patch',
|
||||
Remove: 'remove',
|
||||
} as const
|
||||
|
||||
/** @public */
|
||||
export type RecordOpType = (typeof RecordOpType)[keyof typeof RecordOpType]
|
||||
|
||||
/** @public */
|
||||
export type RecordOp<R extends UnknownRecord> =
|
||||
| [RecordOpType.Put, R]
|
||||
| [RecordOpType.Patch, ObjectDiff]
|
||||
| [RecordOpType.Remove]
|
||||
| [typeof RecordOpType.Put, R]
|
||||
| [typeof RecordOpType.Patch, ObjectDiff]
|
||||
| [typeof RecordOpType.Remove]
|
||||
|
||||
/**
|
||||
* A one-way (non-reversible) diff designed for small json footprint. These are mainly intended to
|
||||
|
@ -60,20 +63,22 @@ export const getNetworkDiff = <R extends UnknownRecord>(
|
|||
}
|
||||
|
||||
/** @public */
|
||||
export enum ValueOpType {
|
||||
Put = 'put',
|
||||
Delete = 'delete',
|
||||
Append = 'append',
|
||||
Patch = 'patch',
|
||||
}
|
||||
export const ValueOpType = {
|
||||
Put: 'put',
|
||||
Delete: 'delete',
|
||||
Append: 'append',
|
||||
Patch: 'patch',
|
||||
} as const
|
||||
export type ValueOpType = (typeof ValueOpType)[keyof typeof ValueOpType]
|
||||
|
||||
/** @public */
|
||||
export type PutOp = [type: ValueOpType.Put, value: unknown]
|
||||
export type PutOp = [type: typeof ValueOpType.Put, value: unknown]
|
||||
/** @public */
|
||||
export type AppendOp = [type: ValueOpType.Append, values: unknown[], offset: number]
|
||||
export type AppendOp = [type: typeof ValueOpType.Append, values: unknown[], offset: number]
|
||||
/** @public */
|
||||
export type PatchOp = [type: ValueOpType.Patch, diff: ObjectDiff]
|
||||
export type PatchOp = [type: typeof ValueOpType.Patch, diff: ObjectDiff]
|
||||
/** @public */
|
||||
export type DeleteOp = [type: ValueOpType.Delete]
|
||||
export type DeleteOp = [type: typeof ValueOpType.Delete]
|
||||
|
||||
/** @public */
|
||||
export type ValueOp = PutOp | AppendOp | PatchOp | DeleteOp
|
||||
|
|
|
@ -5,12 +5,16 @@ import { NetworkDiff, ObjectDiff, RecordOpType } from './diff'
|
|||
export const TLSYNC_PROTOCOL_VERSION = 5
|
||||
|
||||
/** @public */
|
||||
export enum TLIncompatibilityReason {
|
||||
ClientTooOld = 'clientTooOld',
|
||||
ServerTooOld = 'serverTooOld',
|
||||
InvalidRecord = 'invalidRecord',
|
||||
InvalidOperation = 'invalidOperation',
|
||||
}
|
||||
export const TLIncompatibilityReason = {
|
||||
ClientTooOld: 'clientTooOld',
|
||||
ServerTooOld: 'serverTooOld',
|
||||
InvalidRecord: 'invalidRecord',
|
||||
InvalidOperation: 'invalidOperation',
|
||||
} as const
|
||||
|
||||
/** @public */
|
||||
export type TLIncompatibilityReason =
|
||||
(typeof TLIncompatibilityReason)[keyof typeof TLIncompatibilityReason]
|
||||
|
||||
/** @public */
|
||||
export type TLSocketServerSentEvent<R extends UnknownRecord> =
|
||||
|
@ -55,7 +59,7 @@ export type TLPushRequest<R extends UnknownRecord> =
|
|||
| {
|
||||
type: 'push'
|
||||
clientClock: number
|
||||
presence: [RecordOpType.Patch, ObjectDiff] | [RecordOpType.Put, R]
|
||||
presence: [typeof RecordOpType.Patch, ObjectDiff] | [typeof RecordOpType.Put, R]
|
||||
}
|
||||
| {
|
||||
type: 'push'
|
||||
|
|
|
@ -109,7 +109,7 @@ describe('TLServer', () => {
|
|||
expect(server.roomState?.persistenceKey).toBe('test-persistence-key')
|
||||
expect(server.roomState?.room.sessions.size).toBe(1)
|
||||
expect(server.roomState?.room.sessions.get('test-session-key')?.state).toBe(
|
||||
RoomSessionState.AWAITING_CONNECT_MESSAGE
|
||||
RoomSessionState.AwaitingConnectMessage
|
||||
)
|
||||
})
|
||||
|
||||
|
@ -135,7 +135,7 @@ describe('TLServer', () => {
|
|||
sockets.client.on('message', onClientMessage)
|
||||
|
||||
expect(server.roomState?.room.sessions.get('test-session-key')?.state).toBe(
|
||||
RoomSessionState.AWAITING_CONNECT_MESSAGE
|
||||
RoomSessionState.AwaitingConnectMessage
|
||||
)
|
||||
|
||||
for (const chunk of chunks) {
|
||||
|
@ -145,7 +145,7 @@ describe('TLServer', () => {
|
|||
await receivedPromise
|
||||
|
||||
expect(server.roomState?.room.sessions.get('test-session-key')?.state).toBe(
|
||||
RoomSessionState.CONNECTED
|
||||
RoomSessionState.Connected
|
||||
)
|
||||
|
||||
expect(onClientMessage).toHaveBeenCalledTimes(1)
|
||||
|
|
Loading…
Reference in a new issue