Path: blob/master/src/packages/conat/persist/util.ts
1453 views
/*12Maybe storage available as a service.34This code is similar to the changefeed server, because5it provides a changefeed on a given persist storage,6and a way to see values.78DEVELOPMENT:910Change to the packages/backend directory and run node.1112TERMINAL 1: This sets up the environment and starts the server running:1314require('@cocalc/backend/conat/persist').initServer()151617TERMINAL 2: In another node session, create a client:1819user = {account_id:'00000000-0000-4000-8000-000000000000'}; storage = {path:'a.db'}; const {id, stream} = await require('@cocalc/backend/conat/persist').getAll({user, storage}); console.log({id}); for await(const x of stream) { console.log(x.data) }; console.log("DONE")2021// client also does this periodically to keep subscription alive:2223await renew({user, id })2425TERMINAL 3:2627user = {account_id:'00000000-0000-4000-8000-000000000000'}; storage = {path:'a.db'}; const {set,get} = require('@cocalc/backend/conat/persist'); const { messageData } =require("@cocalc/conat/core/client"); 0;2829await set({user, storage, messageData:messageData('hi')})3031await get({user, storage, seq:1})3233await set({user, storage, key:'bella', messageData:messageData('hi', {headers:{x:10}})})3435await get({user, storage, key:'bella'})3637Also getAll using start_seq:3839cf = const {id, stream} = await require('@cocalc/backend/conat/persist').getAll({user, storage, start_seq:10}); for await(const x of stream) { console.log(x) };40*/4142import { assertHasWritePermission } from "./auth";43import { pstream, PersistentStream } from "./storage";44import { join } from "path";45import { syncFiles, ensureContainingDirectoryExists } from "./context";4647// this is per-server -- and "user" means where the resource is, usually48// a given project. E.g., 500 streams in a project, across many users.49export const MAX_PER_USER = 500;50export const MAX_GLOBAL = 10000;51export const RESOURCE = "persistent storage";5253//import { getLogger } from "@cocalc/conat/client";54//const logger = getLogger("persist:util");5556export const SERVICE = "persist";5758export type User = {59account_id?: string;60project_id?: string;61hub_id?: string;62};6364export function persistSubject({ account_id, project_id }: User) {65if (account_id) {66return `${SERVICE}.account-${account_id}`;67} else if (project_id) {68return `${SERVICE}.project-${project_id}`;69} else {70return `${SERVICE}.hub`;71}72}7374export async function getStream({75subject,76storage,77}): Promise<PersistentStream> {78// this permsissions check should always work and use should79// never see an error here, since80// the same check runs on the client before the message is sent to the81// persist storage. However a malicious user would hit this.82// IMPORTANT: must be here so error *code* also sent back.83assertHasWritePermission({84subject,85path: storage.path,86});87const path = join(syncFiles.local, storage.path);88await ensureContainingDirectoryExists(path);89return pstream({ ...storage, path });90}91929394