surrealdb.node icon indicating copy to clipboard operation
surrealdb.node copied to clipboard

Live queries not working with NodeJS embedded engine

Open Jonovono opened this issue 8 months ago • 1 comments

Can't seem to get this working. Is it expected to work, or am I doing something wrong?

  // Create a new SurrealDB instance with Node engine
  const db = new Surreal({
    engines: surrealdbNodeEngines(),
  });

  try {
    // Connect to SurrealDB with SurrealKV
    await db.connect("surrealkv://surreal-data");

    // Use a specific namespace and database
    await db.use({ namespace: "test", database: "test" });

    // Clean up existing tables
    await db.query(`REMOVE TABLE IF EXISTS person;`);

    // Define schema for person table
    await db.query(`
      DEFINE TABLE person SCHEMAFUL;
      DEFINE FIELD name ON person TYPE string;
      DEFINE FIELD age ON person TYPE int;
      DEFINE FIELD email ON person TYPE option<string>;
      DEFINE FIELD city ON person TYPE option<string>;
      DEFINE FIELD updated_at ON person TYPE datetime DEFAULT time::now();
    `);

    console.log("\n=== Setting up LIVE SELECT with filter ===");

    // Set up a live query with a filter - only get people older than 30
    const liveFilterCallback = (action: string, result: any) => {
      if (action === 'CLOSE') {
        console.log("Live filtered query closed");
        return;
      }

      console.log(`[Filtered] ${action} action received:`, result);
    };

    let filterUUID = (await db.query('LIVE SELECT * FROM person'))[0];
    await db.subscribeLive(filterUUID as Uuid, liveFilterCallback);

    await db.create<Person>("person", {
      name: "Test Under",
      age: 35,
      city: "Test City",
    });

    await db.create<Person>("person", {
      name: "Test Over",
      age: 105,
      city: "Test City",
    });

Jonovono avatar Apr 01 '25 23:04 Jonovono

Hmm, confirmed even the table db.live arn't working with node engine:

import Surreal from "surrealdb";
import { surrealdbNodeEngines } from "@surrealdb/node";
import { surrealdbWasmEngines } from "@surrealdb/wasm";

// Interface for our data model
interface Person {
  id?: string;
  name: string;
  age: number;
  email?: string;
  updated_at?: string;
  [key: string]: unknown;
}

async function main(): Promise<void> {
  console.log("=== SurrealDB Live Subscriptions Test ===");

  // Create a new SurrealDB instance with Node engine
  const db = new Surreal({
    engines: surrealdbNodeEngines(),
    // engines: surrealdbWasmEngines()
  });

  try {
    // Connect to SurrealDB with SurrealKV
    // await db.connect("surrealkv://surreal-data");
    await db.connect("mem://");

    // Use a specific namespace and database
    await db.use({ namespace: "test", database: "test" });

    // Clean up existing tables
    await db.query(`REMOVE TABLE IF EXISTS person;`);

    // Define schema for person table
    await db.query(`
      DEFINE TABLE person SCHEMAFUL;
      DEFINE FIELD name ON person TYPE string;
      DEFINE FIELD age ON person TYPE int;
      DEFINE FIELD email ON person TYPE option<string>;
      DEFINE FIELD updated_at ON person TYPE datetime DEFAULT time::now();
    `);

    console.log("\n=== Setting up live subscription ===");

    // Set up a live query subscription to person table
    // The callback takes action and result as separate parameters
    const liveCallback = (action: string, result: any) => {
      if (action === 'CLOSE') {
        console.log("Live query closed");
        return;
      }

      console.log(`${action} action received:`, result);
    };

    // Start the live query and get its UUID
    const queryUuid = await db.live<Person>("person", liveCallback, true);
    console.log(`Live query started with UUID: ${queryUuid}`);

    // Alternative method: Use subscribeLive with the UUID
    // await db.subscribeLive(queryUuid, liveCallback);

    console.log("\n=== Performing data operations ===");

    // Create a person - should trigger a CREATE action
    console.log("Creating a person...");
    const person1 = await db.create<Person>("person", {
      name: "Alice Smith",
      age: 32,
      email: "[email protected]",
    });
    console.log("Person created:", person1);

    // Wait a second to see the notification
    await new Promise(resolve => setTimeout(resolve, 1000));

    // Update the person - should trigger an UPDATE action
    console.log("\nUpdating the person...");
    const personId = (person1[0] as any).id.id;
    await db.query(`
      UPDATE person:${personId} SET 
        age = 33, 
        updated_at = time::now()
    `);
    console.log("Person updated");

    // Wait a second to see the notification
    await new Promise(resolve => setTimeout(resolve, 1000));

    // Delete the person - should trigger a DELETE action
    console.log("\nDeleting the person...");
    await db.delete(`person:${personId}`);
    console.log("Person deleted");

    // Wait a second to see the notification
    await new Promise(resolve => setTimeout(resolve, 1000));

    // Create a couple more people to demonstrate killing the subscription
    console.log("\nCreating more people...");
    await db.create<Person>("person", {
      name: "Bob Johnson",
      age: 28,
      email: "[email protected]",
    });

    await db.create<Person>("person", {
      name: "Carol Williams",
      age: 45,
    });

    // Wait a second to see the notifications
    await new Promise(resolve => setTimeout(resolve, 1000));

    // Kill the live query
    console.log("\n=== Killing the live query ===");
    await db.kill(queryUuid);
    console.log("Live query killed");

    // This creation won't trigger a notification since the query is killed
    console.log("\nCreating another person (should not trigger notification)...");
    await db.create<Person>("person", {
      name: "Dave Brown",
      age: 39,
      email: "[email protected]",
    });

    console.log("\n=== Test completed ===");

    // Clean up
    await db.query("REMOVE TABLE person");
  } catch (err) {
    console.error("Error:", (err as Error).message);
  } finally {
    // Close the connection
    await db.close();
  }
}

// Run the test
main().catch(console.error); 

Jonovono avatar Apr 02 '25 20:04 Jonovono