Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
sagemathinc
GitHub Repository: sagemathinc/cocalc
Path: blob/master/src/packages/conat/persist/util.ts
1453 views
1
/*
2
3
Maybe storage available as a service.
4
5
This code is similar to the changefeed server, because
6
it provides a changefeed on a given persist storage,
7
and a way to see values.
8
9
DEVELOPMENT:
10
11
Change to the packages/backend directory and run node.
12
13
TERMINAL 1: This sets up the environment and starts the server running:
14
15
require('@cocalc/backend/conat/persist').initServer()
16
17
18
TERMINAL 2: In another node session, create a client:
19
20
user = {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")
21
22
// client also does this periodically to keep subscription alive:
23
24
await renew({user, id })
25
26
TERMINAL 3:
27
28
user = {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;
29
30
await set({user, storage, messageData:messageData('hi')})
31
32
await get({user, storage, seq:1})
33
34
await set({user, storage, key:'bella', messageData:messageData('hi', {headers:{x:10}})})
35
36
await get({user, storage, key:'bella'})
37
38
Also getAll using start_seq:
39
40
cf = const {id, stream} = await require('@cocalc/backend/conat/persist').getAll({user, storage, start_seq:10}); for await(const x of stream) { console.log(x) };
41
*/
42
43
import { assertHasWritePermission } from "./auth";
44
import { pstream, PersistentStream } from "./storage";
45
import { join } from "path";
46
import { syncFiles, ensureContainingDirectoryExists } from "./context";
47
48
// this is per-server -- and "user" means where the resource is, usually
49
// a given project. E.g., 500 streams in a project, across many users.
50
export const MAX_PER_USER = 500;
51
export const MAX_GLOBAL = 10000;
52
export const RESOURCE = "persistent storage";
53
54
//import { getLogger } from "@cocalc/conat/client";
55
//const logger = getLogger("persist:util");
56
57
export const SERVICE = "persist";
58
59
export type User = {
60
account_id?: string;
61
project_id?: string;
62
hub_id?: string;
63
};
64
65
export function persistSubject({ account_id, project_id }: User) {
66
if (account_id) {
67
return `${SERVICE}.account-${account_id}`;
68
} else if (project_id) {
69
return `${SERVICE}.project-${project_id}`;
70
} else {
71
return `${SERVICE}.hub`;
72
}
73
}
74
75
export async function getStream({
76
subject,
77
storage,
78
}): Promise<PersistentStream> {
79
// this permsissions check should always work and use should
80
// never see an error here, since
81
// the same check runs on the client before the message is sent to the
82
// persist storage. However a malicious user would hit this.
83
// IMPORTANT: must be here so error *code* also sent back.
84
assertHasWritePermission({
85
subject,
86
path: storage.path,
87
});
88
const path = join(syncFiles.local, storage.path);
89
await ensureContainingDirectoryExists(path);
90
return pstream({ ...storage, path });
91
}
92
93
94