ueberdosis / hocuspocus

The CRDT Yjs WebSocket backend for conflict-free real-time collaboration in your app.
https://tiptap.dev/docs/hocuspocus/introduction
MIT License
1.34k stars 129 forks source link

Disconnection After First Reply in Hocuspocus on AWS Fargate #871

Closed AitBaali-Hamza-bcg closed 2 weeks ago

AitBaali-Hamza-bcg commented 4 weeks ago

Description The WebSocket connection to the Hocuspocus server drops and is ignored after the first reply from the server. The connection successfully opens, authentication and sync messages are exchanged, but the connection is subsequently closed without an error message. The issue seems to occur after the first document sync and awareness update.

Steps to reproduce the bug Steps to reproduce the behavior:

  1. Normal connection to hocuspocus deployed in AWS Fargate

Expected behavior The WebSocket connection should remain open after the first reply from the server, allowing continuous synchronization of the document and awareness updates without being disconnected.

Screenshot, video, or GIF from browser:

Screenshot 2024-10-29 at 12 57 01 Screenshot 2024-10-29 at 12 56 51

From a script:

> node hocus_debug.js

🔄 Connection status changed: "connecting"
🔓 WebSocket connection opened.
🔓 WebSocket connection opened.
📤 Outgoing message: AuthenticationMessage {
  encoder: Encoder {
    cpos: 40,
    cbuf: Uint8Array(100) [
      15, 109, 121,  45, 100, 111, 99, 117, 109, 101, 110, 116,
      47, 110, 101, 119,   2,   0, 21,  72,  79,  67,  85,  83,
      80,  79,  67,  85,  83,  95, 65,  71,  69,  78,  84,  95,
      83,  89,  78,  67,   0,   0,  0,   0,   0,   0,   0,   0,
       0,   0,   0,   0,   0,   0,  0,   0,   0,   0,   0,   0,
       0,   0,   0,   0,   0,   0,  0,   0,   0,   0,   0,   0,
       0,   0,   0,   0,   0,   0,  0,   0,   0,   0,   0,   0,
       0,   0,   0,   0,   0,   0,  0,   0,   0,   0,   0,   0,
       0,   0,   0,   0
    ],
    bufs: []
  },
  type: 2,
  description: 'Authentication'
}
📤 Outgoing message: SyncStepOneMessage {
  encoder: Encoder {
    cpos: 20,
    cbuf: Uint8Array(100) [
      15, 109, 121,  45, 100, 111, 99, 117, 109, 101, 110, 116,
      47, 110, 101, 119,   0,   0,  1,   0,   0,   0,   0,   0,
       0,   0,   0,   0,   0,   0,  0,   0,   0,   0,   0,   0,
       0,   0,   0,   0,   0,   0,  0,   0,   0,   0,   0,   0,
       0,   0,   0,   0,   0,   0,  0,   0,   0,   0,   0,   0,
       0,   0,   0,   0,   0,   0,  0,   0,   0,   0,   0,   0,
       0,   0,   0,   0,   0,   0,  0,   0,   0,   0,   0,   0,
       0,   0,   0,   0,   0,   0,  0,   0,   0,   0,   0,   0,
       0,   0,   0,   0
    ],
    bufs: []
  },
  type: 0,
  description: 'First sync step'
}
📤 Outgoing message: AwarenessMessage {
  encoder: Encoder {
    cpos: 28,
    cbuf: Uint8Array(100) [
      15, 109, 121,  45, 100, 111, 99, 117, 109, 101, 110, 116,
      47, 110, 101, 119,   1,  10,  1, 230, 159, 151, 206,   1,
       0,   2, 123, 125,   0,   0,  0,   0,   0,   0,   0,   0,
       0,   0,   0,   0,   0,   0,  0,   0,   0,   0,   0,   0,
       0,   0,   0,   0,   0,   0,  0,   0,   0,   0,   0,   0,
       0,   0,   0,   0,   0,   0,  0,   0,   0,   0,   0,   0,
       0,   0,   0,   0,   0,   0,  0,   0,   0,   0,   0,   0,
       0,   0,   0,   0,   0,   0,  0,   0,   0,   0,   0,   0,
       0,   0,   0,   0
    ],
    bufs: []
  },
  type: 1,
  description: 'Awareness states update'
}
🔄 Connection status changed: "connected"
✅ Successfully connected to the Hocuspocus server
Network Info: ws://localhost:1234
📩 Message from server: {
  event: MessageEvent {
    [Symbol(kTarget)]: WebSocket {
      _events: [Object: null prototype],
      _eventsCount: 4,
      _maxListeners: undefined,
      _binaryType: 'arraybuffer',
      _closeCode: 1006,
      _closeFrameReceived: false,
      _closeFrameSent: false,
      _closeMessage: <Buffer >,
      _closeTimer: null,
      _errorEmitted: false,
      _extensions: {},
      _paused: false,
      _protocol: '',
      _readyState: 1,
      _receiver: [Receiver],
      _sender: [Sender],
      _socket: [TLSSocket],
      _bufferedAmount: 0,
      _isServer: false,
      _redirects: 0,
      _autoPong: true,
      _url: 'ws://localhost:1234',
      _req: null,
      identifier: 1,
      [Symbol(kCapture)]: false
    },
    [Symbol(kType)]: 'message',
    [Symbol(kData)]: ArrayBuffer {
      [Uint8Contents]: <0f 6d 79 2d 64 6f 63 75 6d 65 6e 74 2f 6e 65 77 02 02 0a 72 65 61 64 2d 77 72 69 74 65>,
      byteLength: 29
    }
  },
  message: IncomingMessage {
    data: ArrayBuffer {
      [Uint8Contents]: <0f 6d 79 2d 64 6f 63 75 6d 65 6e 74 2f 6e 65 77 02 02 0a 72 65 61 64 2d 77 72 69 74 65>,
      byteLength: 29
    },
    encoder: Encoder { cpos: 0, cbuf: [Uint8Array], bufs: [] },
    decoder: Decoder { arr: [Uint8Array], pos: 0 }
  }
}
🔑 Authenticated successfully.
✍️ Making a local change to the document...
📥 Document updated from the server: Hello Hocuspocus!
📤 Outgoing message: UpdateMessage {
  encoder: Encoder {
    cpos: 60,
    cbuf: Uint8Array(100) [
       15, 109, 121,  45, 100, 111,  99, 117, 109, 101, 110, 116,
       47, 110, 101, 119,   0,   2,  41,   1,   1, 230, 159, 151,
      206,   1,   0,   4,   1,  11, 115, 104,  97, 114, 101, 100,
       45, 116, 101, 120, 116,  17,  72, 101, 108, 108, 111,  32,
       72, 111,  99, 117, 115, 112, 111,  99, 117, 115,  33,   0,
        0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
        0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
        0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
        0,   0,   0,   0
    ],
    bufs: []
  },
  type: 0,
  description: 'A document update'
}
📤 Document after local update: Hello Hocuspocus!
🔗 WebSocket is open and connected
🔗 WebSocket is open and connected
👥 Awareness updated: { added: undefined, updated: undefined, removed: undefined }
📤 Outgoing message: AwarenessMessage {
  encoder: Encoder {
    cpos: 28,
    cbuf: Uint8Array(100) [
      15, 109, 121,  45, 100, 111, 99, 117, 109, 101, 110, 116,
      47, 110, 101, 119,   1,  10,  1, 230, 159, 151, 206,   1,
       1,   2, 123, 125,   0,   0,  0,   0,   0,   0,   0,   0,
       0,   0,   0,   0,   0,   0,  0,   0,   0,   0,   0,   0,
       0,   0,   0,   0,   0,   0,  0,   0,   0,   0,   0,   0,
       0,   0,   0,   0,   0,   0,  0,   0,   0,   0,   0,   0,
       0,   0,   0,   0,   0,   0,  0,   0,   0,   0,   0,   0,
       0,   0,   0,   0,   0,   0,  0,   0,   0,   0,   0,   0,
       0,   0,   0,   0
    ],
    bufs: []
  },
  type: 1,
  description: 'Awareness states update'
}
🔗 WebSocket is open and connected
🔗 WebSocket is open and connected
🔗 WebSocket is open and connected
👥 Awareness updated: { added: undefined, updated: undefined, removed: undefined }
📤 Outgoing message: AwarenessMessage {
  encoder: Encoder {
    cpos: 28,
    cbuf: Uint8Array(100) [
      15, 109, 121,  45, 100, 111, 99, 117, 109, 101, 110, 116,
      47, 110, 101, 119,   1,  10,  1, 230, 159, 151, 206,   1,
       2,   2, 123, 125,   0,   0,  0,   0,   0,   0,   0,   0,
       0,   0,   0,   0,   0,   0,  0,   0,   0,   0,   0,   0,
       0,   0,   0,   0,   0,   0,  0,   0,   0,   0,   0,   0,
       0,   0,   0,   0,   0,   0,  0,   0,   0,   0,   0,   0,
       0,   0,   0,   0,   0,   0,  0,   0,   0,   0,   0,   0,
       0,   0,   0,   0,   0,   0,  0,   0,   0,   0,   0,   0,
       0,   0,   0,   0
    ],
    bufs: []
  },
  type: 1,
  description: 'Awareness states update'
}
🔗 WebSocket is open and connected
🔄 Connection status changed: "disconnected"
❌ Disconnected from server: CloseEvent {
  [Symbol(kTarget)]: <ref *1> WebSocket {
    _events: [Object: null prototype] {},
    _eventsCount: 0,
    _maxListeners: undefined,
    _binaryType: 'arraybuffer',
    _closeCode: 1005,
    _closeFrameReceived: true,
    _closeFrameSent: true,
    _closeMessage: <Buffer >,
    _closeTimer: Timeout {
      _idleTimeout: -1,
      _idlePrev: null,
      _idleNext: null,
      _idleStart: 33121,
      _onTimeout: null,
      _timerArgs: undefined,
      _repeat: null,
      _destroyed: true,
      [Symbol(refed)]: true,
      [Symbol(kHasPrimitive)]: false,
      [Symbol(asyncId)]: 77,
      [Symbol(triggerId)]: 36
    },
    _errorEmitted: false,
    _extensions: {},
    _paused: false,
    _protocol: '',
    _readyState: 3,
    _receiver: Receiver {
      _writableState: [WritableState],
      _events: [Object: null prototype] {},
      _eventsCount: 0,
      _maxListeners: undefined,
      _allowSynchronousEvents: true,
      _binaryType: 'arraybuffer',
      _extensions: {},
      _isServer: false,
      _maxPayload: 104857600,
      _skipUTF8Validation: false,
      _bufferedBytes: 0,
      _buffers: [],
      _compressed: false,
      _payloadLength: 0,
      _mask: undefined,
      _fragmented: 0,
      _masked: false,
      _fin: true,
      _opcode: 8,
      _totalPayloadLength: 0,
      _messageLength: 0,
      _fragments: [],
      _errored: false,
      _loop: false,
      _state: 0,
      [Symbol(kCapture)]: false,
      [Symbol(websocket)]: [Circular *1]
    },
    _sender: Sender {
      _extensions: {},
      _socket: [TLSSocket],
      _firstFragment: true,
      _compress: false,
      _bufferedBytes: 0,
      _queue: [],
      _state: 0,
      onerror: [Function: senderOnError],
      [Symbol(websocket)]: [Circular *1]
    },
    _socket: TLSSocket {
      _tlsOptions: [Object],
      _secureEstablished: true,
      _securePending: false,
      _newSessionPending: false,
      _controlReleased: true,
      secureConnecting: false,
      _SNICallback: null,
      servername: 'localhost:1234',
      alpnProtocol: false,
      authorized: true,
      authorizationError: null,
      encrypted: true,
      _events: [Object: null prototype],
      _eventsCount: 5,
      connecting: false,
      _hadError: false,
      _parent: null,
      _host: 'localhost:1234',
      _closeAfterHandlingError: false,
      _readableState: [ReadableState],
      _maxListeners: undefined,
      _writableState: [WritableState],
      allowHalfOpen: false,
      _sockname: null,
      _pendingData: null,
      _pendingEncoding: '',
      server: undefined,
      _server: null,
      ssl: null,
      _requestCert: true,
      _rejectUnauthorized: true,
      parser: null,
      _httpMessage: null,
      timeout: 0,
      write: [Function: writeAfterFIN],
      [Symbol(alpncallback)]: null,
      [Symbol(res)]: null,
      [Symbol(verified)]: true,
      [Symbol(pendingSession)]: null,
      [Symbol(async_id_symbol)]: 39,
      [Symbol(kHandle)]: null,
      [Symbol(lastWriteQueueSize)]: 0,
      [Symbol(timeout)]: null,
      [Symbol(kBuffer)]: null,
      [Symbol(kBufferCb)]: null,
      [Symbol(kBufferGen)]: null,
      [Symbol(kCapture)]: false,
      [Symbol(kSetNoDelay)]: true,
      [Symbol(kSetKeepAlive)]: false,
      [Symbol(kSetKeepAliveInitialDelay)]: 0,
      [Symbol(kBytesRead)]: 610,
      [Symbol(kBytesWritten)]: 483,
      [Symbol(connect-options)]: [Object],
      [Symbol(websocket)]: undefined
    },
    _bufferedAmount: 0,
    _isServer: false,
    _redirects: 0,
    _autoPong: true,
    _url: 'ws://localhost:1234',
    _req: null,
    identifier: 1,
    [Symbol(kCapture)]: false
  },
  [Symbol(kType)]: 'close',
  [Symbol(kCode)]: 1005,
  [Symbol(kReason)]: '',
  [Symbol(kWasClean)]: true
}
🔄 Connection status changed: "connecting"
🚪 Connection closed: CloseEvent {
  [Symbol(kTarget)]: <ref *1> WebSocket {
    _events: [Object: null prototype] {},
    _eventsCount: 0,
    _maxListeners: undefined,
    _binaryType: 'arraybuffer',
    _closeCode: 1005,
    _closeFrameReceived: true,
    _closeFrameSent: true,
    _closeMessage: <Buffer >,
    _closeTimer: Timeout {
      _idleTimeout: -1,
      _idlePrev: null,
      _idleNext: null,
      _idleStart: 33121,
      _onTimeout: null,
      _timerArgs: undefined,
      _repeat: null,
      _destroyed: true,
      [Symbol(refed)]: true,
      [Symbol(kHasPrimitive)]: false,
      [Symbol(asyncId)]: 77,
      [Symbol(triggerId)]: 36
    },
    _errorEmitted: false,
    _extensions: {},
    _paused: false,
    _protocol: '',
    _readyState: 3,
    _receiver: Receiver {
      _writableState: [WritableState],
      _events: [Object: null prototype] {},
      _eventsCount: 0,
      _maxListeners: undefined,
      _allowSynchronousEvents: true,
      _binaryType: 'arraybuffer',
      _extensions: {},
      _isServer: false,
      _maxPayload: 104857600,
      _skipUTF8Validation: false,
      _bufferedBytes: 0,
      _buffers: [],
      _compressed: false,
      _payloadLength: 0,
      _mask: undefined,
      _fragmented: 0,
      _masked: false,
      _fin: true,
      _opcode: 8,
      _totalPayloadLength: 0,
      _messageLength: 0,
      _fragments: [],
      _errored: false,
      _loop: false,
      _state: 0,
      [Symbol(kCapture)]: false,
      [Symbol(websocket)]: [Circular *1]
    },
    _sender: Sender {
      _extensions: {},
      _socket: [TLSSocket],
      _firstFragment: true,
      _compress: false,
      _bufferedBytes: 0,
      _queue: [],
      _state: 0,
      onerror: [Function: senderOnError],
      [Symbol(websocket)]: [Circular *1]
    },
    _socket: TLSSocket {
      _tlsOptions: [Object],
      _secureEstablished: true,
      _securePending: false,
      _newSessionPending: false,
      _controlReleased: true,
      secureConnecting: false,
      _SNICallback: null,
      servername: 'localhost',
      alpnProtocol: false,
      authorized: true,
      authorizationError: null,
      encrypted: true,
      _events: [Object: null prototype],
      _eventsCount: 5,
      connecting: false,
      _hadError: false,
      _parent: null,
      _host: 'localhost:1234',
      _closeAfterHandlingError: false,
      _readableState: [ReadableState],
      _maxListeners: undefined,
      _writableState: [WritableState],
      allowHalfOpen: false,
      _sockname: null,
      _pendingData: null,
      _pendingEncoding: '',
      server: undefined,
      _server: null,
      ssl: null,
      _requestCert: true,
      _rejectUnauthorized: true,
      parser: null,
      _httpMessage: null,
      timeout: 0,
      write: [Function: writeAfterFIN],
      [Symbol(alpncallback)]: null,
      [Symbol(res)]: null,
      [Symbol(verified)]: true,
      [Symbol(pendingSession)]: null,
      [Symbol(async_id_symbol)]: 39,
      [Symbol(kHandle)]: null,
      [Symbol(lastWriteQueueSize)]: 0,
      [Symbol(timeout)]: null,
      [Symbol(kBuffer)]: null,
      [Symbol(kBufferCb)]: null,
      [Symbol(kBufferGen)]: null,
      [Symbol(kCapture)]: false,
      [Symbol(kSetNoDelay)]: true,
      [Symbol(kSetKeepAlive)]: false,
      [Symbol(kSetKeepAliveInitialDelay)]: 0,
      [Symbol(kBytesRead)]: 610,
      [Symbol(kBytesWritten)]: 483,
      [Symbol(connect-options)]: [Object],
      [Symbol(websocket)]: undefined
    },
    _bufferedAmount: 0,
    _isServer: false,
    _redirects: 0,
    _autoPong: true,
    _url: 'ws://localhost:1234',
    _req: null,
    identifier: 1,
    [Symbol(kCapture)]: false
  },
  [Symbol(kType)]: 'close',
  [Symbol(kCode)]: 1005,
  [Symbol(kReason)]: '',
  [Symbol(kWasClean)]: true
}
🔓 WebSocket connection opened.
🔓 WebSocket connection opened.
📤 Outgoing message: AuthenticationMessage {
  encoder: Encoder {
    cpos: 40,
    cbuf: Uint8Array(100) [
      15, 109, 121,  45, 100, 111, 99, 117, 109, 101, 110, 116,
      47, 110, 101, 119,   2,   0, 21,  72,  79,  67,  85,  83,
      80,  79,  67,  85,  83,  95, 65,  71,  69,  78,  84,  95,
      83,  89,  78,  67,   0,   0,  0,   0,   0,   0,   0,   0,
       0,   0,   0,   0,   0,   0,  0,   0,   0,   0,   0,   0,
       0,   0,   0,   0,   0,   0,  0,   0,   0,   0,   0,   0,
       0,   0,   0,   0,   0,   0,  0,   0,   0,   0,   0,   0,
       0,   0,   0,   0,   0,   0,  0,   0,   0,   0,   0,   0,
       0,   0,   0,   0
    ],
    bufs: []
  },
  type: 2,
  description: 'Authentication'
}
📤 Outgoing message: SyncStepOneMessage {
  encoder: Encoder {
    cpos: 26,
    cbuf: Uint8Array(100) [
      15, 109, 121,  45, 100, 111, 99, 117, 109, 101, 110, 116,
      47, 110, 101, 119,   0,   0,  7,   1, 230, 159, 151, 206,
       1,  17,   0,   0,   0,   0,  0,   0,   0,   0,   0,   0,
       0,   0,   0,   0,   0,   0,  0,   0,   0,   0,   0,   0,
       0,   0,   0,   0,   0,   0,  0,   0,   0,   0,   0,   0,
       0,   0,   0,   0,   0,   0,  0,   0,   0,   0,   0,   0,
       0,   0,   0,   0,   0,   0,  0,   0,   0,   0,   0,   0,
       0,   0,   0,   0,   0,   0,  0,   0,   0,   0,   0,   0,
       0,   0,   0,   0
    ],
    bufs: []
  },
  type: 0,
  description: 'First sync step'
}
📤 Outgoing message: AwarenessMessage {
  encoder: Encoder {
    cpos: 28,
    cbuf: Uint8Array(100) [
      15, 109, 121,  45, 100, 111, 99, 117, 109, 101, 110, 116,
      47, 110, 101, 119,   1,  10,  1, 230, 159, 151, 206,   1,
       2,   2, 123, 125,   0,   0,  0,   0,   0,   0,   0,   0,
       0,   0,   0,   0,   0,   0,  0,   0,   0,   0,   0,   0,
       0,   0,   0,   0,   0,   0,  0,   0,   0,   0,   0,   0,
       0,   0,   0,   0,   0,   0,  0,   0,   0,   0,   0,   0,
       0,   0,   0,   0,   0,   0,  0,   0,   0,   0,   0,   0,
       0,   0,   0,   0,   0,   0,  0,   0,   0,   0,   0,   0,
       0,   0,   0,   0
    ],
    bufs: []
  },
  type: 1,
  description: 'Awareness states update'
}
🔄 Connection status changed: "connected"
✅ Successfully connected to the Hocuspocus server
Network Info: ws://localhost:1234
📩 Message from server: {
  event: MessageEvent {
    [Symbol(kTarget)]: WebSocket {
      _events: [Object: null prototype],
      _eventsCount: 4,
      _maxListeners: undefined,
      _binaryType: 'arraybuffer',
      _closeCode: 1006,
      _closeFrameReceived: false,
      _closeFrameSent: false,
      _closeMessage: <Buffer >,
      _closeTimer: null,
      _errorEmitted: false,
      _extensions: {},
      _paused: false,
      _protocol: '',
      _readyState: 1,
      _receiver: [Receiver],
      _sender: [Sender],
      _socket: [TLSSocket],
      _bufferedAmount: 0,
      _isServer: false,
      _redirects: 0,
      _autoPong: true,
      _url: 'ws://localhost:1234',
      _req: null,
      identifier: 2,
      [Symbol(kCapture)]: false
    },
    [Symbol(kType)]: 'message',
    [Symbol(kData)]: ArrayBuffer {
      [Uint8Contents]: <0f 6d 79 2d 64 6f 63 75 6d 65 6e 74 2f 6e 65 77 02 02 0a 72 65 61 64 2d 77 72 69 74 65>,
      byteLength: 29
    }
  },
  message: IncomingMessage {
    data: ArrayBuffer {
      [Uint8Contents]: <0f 6d 79 2d 64 6f 63 75 6d 65 6e 74 2f 6e 65 77 02 02 0a 72 65 61 64 2d 77 72 69 74 65>,
      byteLength: 29
    },
    encoder: Encoder { cpos: 0, cbuf: [Uint8Array], bufs: [] },
    decoder: Decoder { arr: [Uint8Array], pos: 0 }
  }
}
🔑 Authenticated successfully.
🔗 WebSocket is open and connected
....

Script :

const crypto = globalThis.cryto || require('crypto');
const WebSocket = require('ws');
global.WebSocket = WebSocket;

const { HocuspocusProvider } = require('@hocuspocus/provider');
const Y = require('yjs');

// Initialize a Yjs document
const document = new Y.Doc();
const url = 'ws://localhost:1234'  // Replace with the actual WebSocket URL of your Hocuspocus server
// Connect to Hocuspocus server
const provider = new HocuspocusProvider({
  url: url,
  name: 'my-document/new',
  document: document,
  token: "HOCUSPOCUS_AGENT_SYNC",

  // Event Handlers
  onOpen: () => {
    console.log('🔓 WebSocket connection opened.');
  },
  onConnect: () => {
    console.log('✅ Successfully connected to the Hocuspocus server');
    console.log('Network Info: ', url);
  },
  onAuthenticated: () => {
    console.log('🔑 Authenticated successfully.');
  },
  onAuthenticationFailed: ({ reason }) => {
    console.log('❌ Authentication failed:', reason);
  },
  onStatus: ({ status }) => {
    console.log(`🔄 Connection status changed: ${JSON.stringify(status)}`);
  },
  onMessage: ({ event, message }) => {
    console.log('📩 Message from server:', { event, message });
  },
  onOutgoingMessage: ({ message }) => {
    console.log('📤 Outgoing message:', message);
  },
  onSynced: ({ state }) => {
    console.log('🔗 Document synced with server:', state);
  },
  onClose: ({ event }) => {
    console.log('🚪 Connection closed:', event);
  },
  onDisconnect: ({ event }) => {
    console.log('❌ Disconnected from server:', event);
  },
  onDestroy: () => {
    console.log('💥 Provider destroyed.');
  },
  onAwarenessUpdate: ({ added, updated, removed }) => {
    console.log('👥 Awareness updated:', { added, updated, removed });
  },
  onAwarenessChange: ({ states }) => {
    console.log('🔄 Awareness states changed:', states);
  },
  onStateless: ({ payload }) => {
    console.log('📦 Stateless message received:', payload);
    // Optionally, you can send a stateless message back to the server
    provider.sendStateless('Custom response message');
  },
  connect: true,
});

// Perform some Yjs operations
const yText = document.getText('shared-text');

// Listen for remote changes
yText.observe(event => {
  console.log('📥 Document updated from the server:', yText.toString());
});

// Simulate a local update to the document
setTimeout(() => {
  console.log('✍️ Making a local change to the document...');
  yText.insert(0, 'Hello Hocuspocus!');
  console.log('📤 Document after local update:', yText.toString());
}, 2000);

// Network log function
setInterval(() => {
  if (provider && provider.status === 'connected') {
    console.log('🔗 WebSocket is open and connected');
  } else {
    console.log('⚡ WebSocket is not open');
  }
}, 5000);

// Catch provider errors globally
provider.on('error', (error) => {
  console.error('⚠️ Provider error:', error);
});

Environment?

Additional context hocuspocus works perfectly locally.

AitBaali-Hamza-bcg commented 2 weeks ago

The issue FIXED. Redis was using in-transit encryption tls (NOTE: without any auth token), Redis extension can connect but couldn't communicate with Redis apparently, and this causes weird issues with Hocuspocus with no errors thrown, I am not sure how Redis extension can affect another part of Hocuspocus like this, but the issue is fixed by properly connecting to Redis by passing the Redis ioredis client to the Redis extension config.