serenity-kit / secsync

Architecture for end-to-end encrypted CRDTs
https://www.secsync.com/
Apache License 2.0
159 stars 6 forks source link

machine state seems to be stuck at connecting without throwing error #98

Closed Joshua-onwuzu closed 1 month ago

Joshua-onwuzu commented 6 months ago

I'm attempting to experiment with SecSync in a React application and have completed the initial setup for Yjs and TipTap using useYjsSync as per the guidelines outlined in here.

I used the provided test WebSocket server wss://secsync.fly.dev . However, I encountered an issue where my state wasn't persisting to the server. Upon inspecting the browser's network tab, I noticed that there was no WebSocket connection being established and the application didn't throw any errors, and the machine state remained stuck in the connecting state. This problem persisted even when I attempted to run the WebSocket server locally.

btw, i was able to get everything up and running together without issues from the docker setup, i am not sure what i am missing here. ws://localhost:4000 in the code below points to the backend service from the repo running locally.

here is my entire react code:

import React, { useEffect, useRef, useState } from 'react'
import sodium, { KeyPair } from 'libsodium-wrappers'
import * as Yjs from 'yjs'
import { useYjsSync } from 'secsync-react-yjs'
import { EditorContent, useEditor } from '@tiptap/react'
import StarterKit from '@tiptap/starter-kit'
import Collaboration from '@tiptap/extension-collaboration'
import uuid from 'react-uuid'

const SecSync = () => {
  const [authorKeyPair] = useState<KeyPair>(() => {
    return sodium.crypto_sign_keypair()
  })
  const yDocRef = useRef<Yjs.Doc>(new Yjs.Doc())
  const documentKey = sodium.crypto_secretbox_keygen()

  const [state, send] = useYjsSync({
    yDoc: yDocRef.current,
    documentId: uuid(),
    signatureKeyPair: authorKeyPair,
    websocketHost: 'ws://localhost:4000',
    websocketSessionKey: 'your-secret-session-key',
    onDocumentUpdated: async ({ knownSnapshotInfo }) => {
      console.log(knownSnapshotInfo, 'knownSnapshotInfo')
    },
    getNewSnapshotData: async ({ id }) => {
      return {
        data: Yjs.encodeStateAsUpdateV2(yDocRef.current),
        key: documentKey,
        publicData: {},
      }
    },
    getSnapshotKey: async (snapshot) => {
      return documentKey
    },
    shouldSendSnapshot: ({ snapshotUpdatesCount }) => {
      // create a new snapshot if the active snapshot has more than 100 updates
      return snapshotUpdatesCount > 100
    },
    isValidClient: async (signingPublicKey: string) => {
      return true
    },
    sodium,
    logging: 'debug',
  })
  const editor = useEditor({
    extensions: [
      StarterKit.configure({
        // the Collaboration extension comes with its own history handling
        history: false,
      }),
      Collaboration.configure({
        document: yDocRef.current,
        field: 'page',
      }),
    ],
  })
  return (
    <div>
      <h1>SECSYNC</h1>
      <EditorContent editor={editor} />
      <div>{state.matches('connected') ? 'CONNECTED' : 'DISCONNECTED'}</div>
      {state.matches('connected') && 'Connected'}
      {state.matches('connecting') && 'Connecting …'}
      {state.matches('disconnected') && 'Disconnected'}
      {state.matches('failed') && 'Error in loading or sending data'}
      <button
        onClick={() => {
          send({ type: 'CONNECT' })
        }}
      >
        Connect
      </button>{' '}
      <button
        onClick={() => {
          send({ type: 'DISCONNECT' })
        }}
      >
        Disconnect
      </button>
    </div>
  )
}

const Test = () => {
  const [libsodiumIsReady, setLibsodiumIsReady] = useState(false)

  useEffect(() => {
    sodium.ready.then(() => {
      setLibsodiumIsReady(true)
    })
  }, [])
  if (!libsodiumIsReady) return <>Loading</>
  return <SecSync />
}

export default Test
nikgraf commented 1 month ago

hey @Joshua-onwuzu, so sorry for the late reply. Somehow this didn't end up in my Github notifications.

I recently upgrade to xstate5 and did important fixes. Will do more this week and then publish a new version. Would you be interested to try again then?

ncallaway commented 1 month ago

@nikgraf I also was having this problem the other day. I'd definitely be willing to test a version 0.2.0 and a 0.2.1 to test a fix

ncallaway commented 1 month ago

I should also mention that when I clone secsync and npm link the packages, I wasn't seeing this issue, so I strongly suspect that your recent changes fixed the issue for me. But I'd be happy to verify on a published npm package.

nikgraf commented 1 month ago

@ncallaway just published a new version, would appreciate if you you can verify that it now works

ncallaway commented 1 month ago

@nikgraf Just tested with secsync@0.4.0 and secsync-server@0.4.0 and it's working for me

nikgraf commented 1 month ago

closing the issue, let me know once it comes up again