🎉 pluv.io is now stable! Read our announcement here

Loading Storage

Listen to when a room is deleted so that when the same room is re-created, users can resume from the same storage as where they left off.

getInitialStorage

Every time a room is freshly created, the getInitialStorage listener will run, and the return value of this function will set the initial value of the room's storage. If this function returns null, it is assumed that no storage was found, and a blank storage will be initialized.

The getInitialStorage function is required if crdt is provided to createIO to prevent cases of lost storage data on intermittent client connections.

// server/io.ts
import { yjs } from "@pluv/crdt-yjs";
import { createIO } from "@pluv/io";
import { platformNode } from "@pluv/platform-node";
import { db } from "./db";

export const io = createIO(
  platformNode({
    // Specify which CRDT to use here
    crdt: yjs,
  }),
  context: () => ({ db }),
);

export const ioServer = io.server({
  // Triggered when a room is freshly created. If the room existed
  // before, you can load the storage state for the room by returning it here
  // This is required if `crdt` has been defined on `createIO`. This is to
  // prevent storage data loss on intermittent connections
  getInitialStorage: async ({ context, room }) => {
    const { db } = context;
    const existingRoom = await db.room.findUnique({ where: { room } });

    return existingRoom?.encodedState ?? null;
  },
});

Using @pluv/platform-pluv

If you are using @pluv/platform-pluv, listeners are webhooks under-the-hood. So first, follow these instructions to setup webhooks for your instance. Then click the storage button from the project webhooks page to enable loading your rooms' initial storage from the selected webhook.

Set getInitialStorage set_initial_storage_webhook

Add listeners

Beyond this, the PluvServer provides several event listeners in which you can hook into and save the room's current storage state. It is recommended that you do not save your room's storage state in a handler that runs too frequently so that your database isn't overly written to.

Our recommendation is to save your room's storage state in onRoomDeleted. And if you need more saves beyond that, to throttle writes per room in event listeners such as onStorageUpdated or onRoomMessage.

Note: Not all event listeners are available when using @pluv/platform-pluv. To learn more, please checkout the quickstart guide.

// ...
export const ioServer = io.server({
  // ...
  // Optional: Triggered when a room is deleted. Callback includes the last
  // value for the room's state for persisting purposes
  onRoomDeleted: async ({ context, encodedState, room }) => {
    const { db } = context;

    await db.room.upsert({
      where: { room },
      create: { encodedState, room },
      update: { encodedState },
    });
  },
  // Optional: Triggered each time any participant sends a new message to
  // other participants
  // It is advised not to perform any heavy operations in this listener
  // due to the frequency of invocations
  onRoomMessage: async ({ context, encodedState, room }) => {
    // ...
  },
  // Optional: Triggered each time the room's storage is updated.
  // It is advised not to perform any heavy operations in this listener
  // due to the frequency of invocations
  onStorageUpdated: ({ context, encodedState, room }) => {
    // ...
  },
  // Optional: Triggered each time a user connects to a room
  onUserConnected: ({ context, encodedState, room, user }) => {
    // ...
  },
  // Optional: Triggered each time a user disconnects from a room
  onUserDisconnected: ({ context, encodedState, room, user }) => {
    // ...
  },
});