unjs / crossws

🔌 Cross-platform WebSocket Servers for Node.js, Deno, Bun and Cloudflare Workers.
https://crossws.unjs.io
Other
340 stars 13 forks source link

peer persistent storage #15

Open JCtapuk opened 6 months ago

JCtapuk commented 6 months ago

Describe the feature

I'm glad that they started developing this library. I looked at the code and noticed that it lacks synchronization between servers. For example, pub/sub sends only within the server. For example, the ability to connect via useStorage('redis') so that it is possible to store all clients and indicate a process identifier to determine which clients are external or internal

This will reduce the number of clients on 1 server and distribute it across several clients. Or what it's called I don't remember

Additional information

JCtapuk commented 6 months ago

@pi0 Example request ohters proccess

async function request<
    Name extends keyof LocalClient,
    Callback extends LocalClient[Name]
  >(clientId: UUID, name: Name, ...params: Parameters<Callback>) {
    if (!(await storage.hasItem(`client:${clientId}`))) {
      throw new Error("No found client remote");
    }

    if (!local[name]) {
      throw new Error("No found call remote");
    }

    const id = randomUUID();

    return new Promise<ReturnType<Callback>>(async (resolve, reject) => {
      const timeout = setTimeout(() => {
        reject("Request timeout");
        clear();
      }, requestAutoTime);

      async function clear() {
        await unwatch();
        await storage.clear(`request:${id}`);
        await storage.clear(`response:${id}`);
      }

      const unwatch = await storage.watch(async (type, key) => {
        if (key == `response:${id}`) {
          const response = await storage.getItem<
            | { error: string; data: null }
            | {
                error: null;
                data: ReturnType<Callback>;
              }
          >(key);

          if (!response) return;
          const { error, data } = response;
          if (error) {
            reject(error);
          } else if (data) {
            resolve(data);
          } else {
            reject("Request failed");
          }

          clearTimeout(timeout);
          clear();
        }
      });

      await storage.setItem(`request:${id}`, {
        clientId,
        name,
        params,
      });
    });
  }

I found old code, and of course the implementation is terrible, but it seems that redis has pub/sub. But since unstorage does not yet support this method. I hope you can come up with something =)

pi0 commented 1 month ago

cloudflare durable objects provide similar infrastructure. We might support a similar feature but it needs async API to be cross platform./