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:
Dan Groshev 2024-03-13 17:18:25 +00:00 committed by GitHub
parent 3767a68f0f
commit a933aaf619
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
5 changed files with 59 additions and 48 deletions

View file

@ -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>

View file

@ -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
}

View file

@ -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

View file

@ -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'

View file

@ -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)