@activeledger/activestorage 4.5.12 → 4.5.14
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/es/cache.d.ts +18 -0
- package/es/cache.d.ts.map +1 -0
- package/es/cache.js +57 -0
- package/es/cache.js.map +1 -0
- package/es/datastore.d.ts +11 -0
- package/es/datastore.d.ts.map +1 -0
- package/es/datastore.js +67 -0
- package/es/datastore.js.map +1 -0
- package/es/driver.d.ts +15 -0
- package/es/driver.d.ts.map +1 -0
- package/es/driver.js +2 -0
- package/es/driver.js.map +1 -0
- package/es/drivers/leveldb.d.ts +20 -0
- package/es/drivers/leveldb.d.ts.map +1 -0
- package/es/drivers/leveldb.js +121 -0
- package/es/drivers/leveldb.js.map +1 -0
- package/es/drivers/rocksdb.d.ts +20 -0
- package/es/drivers/rocksdb.d.ts.map +1 -0
- package/es/drivers/rocksdb.js +98 -0
- package/es/drivers/rocksdb.js.map +1 -0
- package/es/heartbeat.d.ts +6 -0
- package/es/heartbeat.d.ts.map +1 -0
- package/es/heartbeat.js +15 -0
- package/es/heartbeat.js.map +1 -0
- package/es/index.d.ts +3 -0
- package/es/index.d.ts.map +1 -0
- package/es/index.js +3 -0
- package/es/index.js.map +1 -0
- package/es/levelme.d.ts +82 -0
- package/es/levelme.d.ts.map +1 -0
- package/es/levelme.js +488 -0
- package/es/levelme.js.map +1 -0
- package/es/newlinestream.d.ts +3 -0
- package/es/newlinestream.d.ts.map +1 -0
- package/es/newlinestream.js +28 -0
- package/es/newlinestream.js.map +1 -0
- package/es/selfhost.d.ts +2 -0
- package/es/selfhost.d.ts.map +1 -0
- package/es/selfhost.js +479 -0
- package/es/selfhost.js.map +1 -0
- package/es/sse.d.ts +10 -0
- package/es/sse.d.ts.map +1 -0
- package/es/sse.js +41 -0
- package/es/sse.js.map +1 -0
- package/lib/cache.d.ts +18 -0
- package/lib/cache.d.ts.map +1 -0
- package/lib/cache.js +62 -0
- package/lib/cache.js.map +1 -0
- package/lib/datastore.d.ts +11 -0
- package/lib/datastore.d.ts.map +1 -0
- package/lib/datastore.js +94 -0
- package/lib/datastore.js.map +1 -0
- package/lib/driver.d.ts +15 -0
- package/lib/driver.d.ts.map +1 -0
- package/lib/driver.js +3 -0
- package/lib/driver.js.map +1 -0
- package/lib/drivers/leveldb.d.ts +20 -0
- package/lib/drivers/leveldb.d.ts.map +1 -0
- package/lib/drivers/leveldb.js +125 -0
- package/lib/drivers/leveldb.js.map +1 -0
- package/lib/drivers/rocksdb.d.ts +20 -0
- package/lib/drivers/rocksdb.d.ts.map +1 -0
- package/lib/drivers/rocksdb.js +102 -0
- package/lib/drivers/rocksdb.js.map +1 -0
- package/lib/heartbeat.d.ts +6 -0
- package/lib/heartbeat.d.ts.map +1 -0
- package/lib/heartbeat.js +19 -0
- package/lib/heartbeat.js.map +1 -0
- package/lib/index.d.ts +3 -0
- package/lib/index.d.ts.map +1 -0
- package/lib/index.js +6 -0
- package/lib/index.js.map +1 -0
- package/lib/levelme.d.ts +82 -0
- package/lib/levelme.d.ts.map +1 -0
- package/lib/levelme.js +515 -0
- package/lib/levelme.js.map +1 -0
- package/lib/newlinestream.d.ts +3 -0
- package/lib/newlinestream.d.ts.map +1 -0
- package/lib/newlinestream.js +31 -0
- package/lib/newlinestream.js.map +1 -0
- package/lib/selfhost.d.ts +2 -0
- package/lib/selfhost.d.ts.map +1 -0
- package/lib/selfhost.js +504 -0
- package/lib/selfhost.js.map +1 -0
- package/lib/sse.d.ts +10 -0
- package/lib/sse.d.ts.map +1 -0
- package/lib/sse.js +45 -0
- package/lib/sse.js.map +1 -0
- package/package.json +12 -8
- package/src/cache.ts +0 -72
- package/src/datastore.ts +0 -187
- package/src/driver.ts +0 -18
- package/src/drivers/leveldb.ts +0 -145
- package/src/drivers/rocksdb.ts +0 -118
- package/src/heartbeat.ts +0 -60
- package/src/index.ts +0 -25
- package/src/levelme.ts +0 -938
- package/src/newlinestream.ts +0 -32
- package/src/selfhost.ts +0 -1078
- package/src/sse.ts +0 -136
- package/src/types/rocksdb.d.ts +0 -1
- package/tsconfig.json +0 -8
- /package/{src → lib}/fauxton/dashboard.assets/css/styles.d43d3249088a6c04b633.css +0 -0
- /package/{src → lib}/fauxton/dashboard.assets/fonts/fauxtonicon5.eot +0 -0
- /package/{src → lib}/fauxton/dashboard.assets/fonts/fauxtonicon5.ttf +0 -0
- /package/{src → lib}/fauxton/dashboard.assets/fonts/fauxtonicon5.woff +0 -0
- /package/{src → lib}/fauxton/dashboard.assets/fonts/fontawesome-webfont.eot +0 -0
- /package/{src → lib}/fauxton/dashboard.assets/fonts/fontawesome-webfont.ttf +0 -0
- /package/{src → lib}/fauxton/dashboard.assets/fonts/fontawesome-webfont.woff +0 -0
- /package/{src → lib}/fauxton/dashboard.assets/img/activeledger-logo.png +0 -0
- /package/{src → lib}/fauxton/dashboard.assets/img/activeledger.png +0 -0
- /package/{src → lib}/fauxton/dashboard.assets/img/asf-feather-logo.png +0 -0
- /package/{src → lib}/fauxton/dashboard.assets/img/couch-watermark.png +0 -0
- /package/{src → lib}/fauxton/dashboard.assets/img/couchdb-logo.png +0 -0
- /package/{src → lib}/fauxton/dashboard.assets/img/fauxtonicon5.svg +0 -0
- /package/{src → lib}/fauxton/dashboard.assets/img/fontawesome-webfont.svg +0 -0
- /package/{src → lib}/fauxton/dashboard.assets/img/github.png +0 -0
- /package/{src → lib}/fauxton/dashboard.assets/img/googleplus.png +0 -0
- /package/{src → lib}/fauxton/dashboard.assets/img/linkedin.png +0 -0
- /package/{src → lib}/fauxton/dashboard.assets/img/loader.gif +0 -0
- /package/{src → lib}/fauxton/dashboard.assets/img/twitter.png +0 -0
- /package/{src → lib}/fauxton/dashboard.assets/js/bundle.d43d3249088a6c04b633.js +0 -0
- /package/{src → lib}/fauxton/dashboard.assets/js/manifest.a154524a560e5f6f431b.js +0 -0
- /package/{src → lib}/fauxton/dashboard.assets/js/vendor.156793045cdeb7c63707.js +0 -0
- /package/{src → lib}/fauxton/index.html +0 -0
package/src/cache.ts
DELETED
|
@@ -1,72 +0,0 @@
|
|
|
1
|
-
// filterOldTxList on index.ts may be better to use this testing between the 2 will tell.
|
|
2
|
-
|
|
3
|
-
export class Cache<T = any> {
|
|
4
|
-
private data: Map<string, T>;
|
|
5
|
-
private timers: Map<string, NodeJS.Timeout>;
|
|
6
|
-
constructor(private ttl = 1200000) {
|
|
7
|
-
this.data = new Map();
|
|
8
|
-
this.timers = new Map();
|
|
9
|
-
}
|
|
10
|
-
|
|
11
|
-
public set(key: string, value: T, ttl?: number): void {
|
|
12
|
-
if (this.timers.has(key)) {
|
|
13
|
-
clearTimeout(this.timers.get(key));
|
|
14
|
-
}
|
|
15
|
-
this.timers.set(
|
|
16
|
-
key,
|
|
17
|
-
setTimeout(() => this.delete(key), ttl ?? this.ttl)
|
|
18
|
-
);
|
|
19
|
-
this.data.set(key, value);
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
public delete(key: string): void {
|
|
23
|
-
if (this.timers.has(key)) {
|
|
24
|
-
clearTimeout(this.timers.get(key));
|
|
25
|
-
this.timers.delete(key);
|
|
26
|
-
}
|
|
27
|
-
this.data.delete(key);
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
public get(key: string, extend?: number): T | undefined {
|
|
31
|
-
const value = this.data.get(key);
|
|
32
|
-
if (value && extend) {
|
|
33
|
-
// Refresh the TTL
|
|
34
|
-
this.set(key, value, extend);
|
|
35
|
-
}
|
|
36
|
-
return value;
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
public has(key: string): boolean {
|
|
40
|
-
return this.data.has(key);
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
public clear(): void {
|
|
44
|
-
this.data.clear();
|
|
45
|
-
for (const timer of this.timers.values()) {
|
|
46
|
-
clearTimeout(timer);
|
|
47
|
-
}
|
|
48
|
-
this.timers.clear();
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
public size(): number {
|
|
52
|
-
return this.data.size;
|
|
53
|
-
}
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
export class CacheManager {
|
|
57
|
-
private static caches: {
|
|
58
|
-
[index: string]: Cache;
|
|
59
|
-
} = {};
|
|
60
|
-
|
|
61
|
-
public static fetch<T = any>(name: string, ttl?: number): Cache<T> {
|
|
62
|
-
if (!this.caches[name]) {
|
|
63
|
-
this.caches[name] = new Cache(ttl);
|
|
64
|
-
}
|
|
65
|
-
return this.caches[name];
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
public static all(): Cache<any>[] {
|
|
69
|
-
return Object.values(this.caches);
|
|
70
|
-
}
|
|
71
|
-
}
|
|
72
|
-
|
package/src/datastore.ts
DELETED
|
@@ -1,187 +0,0 @@
|
|
|
1
|
-
/*
|
|
2
|
-
* MIT License (MIT)
|
|
3
|
-
* Copyright (c) 2018 Activeledger
|
|
4
|
-
*
|
|
5
|
-
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
-
* of this software and associated documentation files (the "Software"), to deal
|
|
7
|
-
* in the Software without restriction, including without limitation the rights
|
|
8
|
-
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
-
* copies of the Software, and to permit persons to whom the Software is
|
|
10
|
-
* furnished to do so, subject to the following conditions:
|
|
11
|
-
*
|
|
12
|
-
* The above copyright notice and this permission notice shall be included in all
|
|
13
|
-
* copies or substantial portions of the Software.
|
|
14
|
-
*
|
|
15
|
-
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
-
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
-
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
-
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
-
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
-
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
-
* SOFTWARE.
|
|
22
|
-
*/
|
|
23
|
-
|
|
24
|
-
import * as fs from "fs";
|
|
25
|
-
import { promises as fsPromises } from "fs";
|
|
26
|
-
import * as child from "child_process";
|
|
27
|
-
import { ActiveOptions } from "@activeledger/activeoptions";
|
|
28
|
-
import { ActiveLogger } from "@activeledger/activelogger";
|
|
29
|
-
|
|
30
|
-
// Maximum restarts allowed
|
|
31
|
-
const MAX_RESTARTS = 5;
|
|
32
|
-
|
|
33
|
-
// How long until the restart counter is allowed to be reset.
|
|
34
|
-
const MAX_RESTART_RESET_HOURS = 24;
|
|
35
|
-
|
|
36
|
-
/**
|
|
37
|
-
* Manage the self hosted data storage engine
|
|
38
|
-
*
|
|
39
|
-
* @export
|
|
40
|
-
* @class DataStore
|
|
41
|
-
*/
|
|
42
|
-
export class ActiveDataStore {
|
|
43
|
-
// Flag to prevent restart loop
|
|
44
|
-
public isShuttingDown = false;
|
|
45
|
-
|
|
46
|
-
/**
|
|
47
|
-
* Folder location
|
|
48
|
-
*
|
|
49
|
-
* @private
|
|
50
|
-
* @type {string}
|
|
51
|
-
*/
|
|
52
|
-
private dsLocation: string;
|
|
53
|
-
|
|
54
|
-
/**
|
|
55
|
-
* Running process
|
|
56
|
-
*
|
|
57
|
-
* @private
|
|
58
|
-
* @type {child.ChildProcess}
|
|
59
|
-
*/
|
|
60
|
-
private process: child.ChildProcess;
|
|
61
|
-
|
|
62
|
-
/**
|
|
63
|
-
* Keeps track how many time database restart has occured
|
|
64
|
-
* This wont solve the restart problem just reduce the logs
|
|
65
|
-
*
|
|
66
|
-
* @private
|
|
67
|
-
*/
|
|
68
|
-
private restartCounter = 0;
|
|
69
|
-
|
|
70
|
-
/**
|
|
71
|
-
* Keeps track the last time it has restarted. This is used
|
|
72
|
-
* as part of the counter and max retries so long running instances are not
|
|
73
|
-
* effected by this new restriction
|
|
74
|
-
*
|
|
75
|
-
* @private
|
|
76
|
-
* @type {Date}
|
|
77
|
-
*/
|
|
78
|
-
private lastRestart: number = Date.now();
|
|
79
|
-
|
|
80
|
-
/**
|
|
81
|
-
* Creates an instance of DataStore.
|
|
82
|
-
*/
|
|
83
|
-
constructor() {
|
|
84
|
-
// Set Folder Location
|
|
85
|
-
this.dsLocation = ActiveOptions.get<any>("db", {}).selfhost.dir || "./.ds";
|
|
86
|
-
|
|
87
|
-
// Check folder exists
|
|
88
|
-
if (!fs.existsSync(this.dsLocation)) {
|
|
89
|
-
fs.mkdirSync(this.dsLocation);
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
// Start Server, Can't block as server wont return
|
|
93
|
-
ActiveLogger.info(
|
|
94
|
-
"Self-hosted data engine @ http://127.0.0.1:" +
|
|
95
|
-
ActiveOptions.get<any>("db", {}).selfhost.port
|
|
96
|
-
);
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
/**
|
|
100
|
-
* Launch data store process
|
|
101
|
-
*
|
|
102
|
-
* @private
|
|
103
|
-
* @returns {string}
|
|
104
|
-
*/
|
|
105
|
-
public launch(): string {
|
|
106
|
-
const dbInfo = ActiveOptions.get<any>("db", {});
|
|
107
|
-
// Launch Background Database Process
|
|
108
|
-
this.process = child.spawn(
|
|
109
|
-
"node",
|
|
110
|
-
[
|
|
111
|
-
__dirname + "/selfhost.js",
|
|
112
|
-
this.dsLocation,
|
|
113
|
-
`${dbInfo.selfhost.port}`,
|
|
114
|
-
`${dbInfo.selfhost.engine || "level"}`,
|
|
115
|
-
],
|
|
116
|
-
{
|
|
117
|
-
stdio: "inherit",
|
|
118
|
-
}
|
|
119
|
-
);
|
|
120
|
-
|
|
121
|
-
ActiveLogger.info(
|
|
122
|
-
`Self-hosted data engine (${
|
|
123
|
-
dbInfo.selfhost.engine || "level"
|
|
124
|
-
}) : Starting Up (${this.process.pid})`
|
|
125
|
-
);
|
|
126
|
-
|
|
127
|
-
// Store the PID for stop command
|
|
128
|
-
this.storePid(this.process.pid || 0);
|
|
129
|
-
|
|
130
|
-
// Listen for possible exits
|
|
131
|
-
this.process.on("exit", (code: number, signal: string) => {
|
|
132
|
-
// Just restart as we need the database up
|
|
133
|
-
ActiveLogger.error(
|
|
134
|
-
`Self-hosted data engine has shutdown (${code} : ${
|
|
135
|
-
signal || "No Signal"
|
|
136
|
-
})`
|
|
137
|
-
);
|
|
138
|
-
// As its an attached process killing activeledger will prevent this restart
|
|
139
|
-
// If killed via activeledger --stop check for SIGTERM signal and don't restart if it is
|
|
140
|
-
if (
|
|
141
|
-
!this.isShuttingDown &&
|
|
142
|
-
signal !== "SIGTERM" &&
|
|
143
|
-
MAX_RESTARTS >= this.restartCounter
|
|
144
|
-
) {
|
|
145
|
-
this.restartCounter++;
|
|
146
|
-
this.launch();
|
|
147
|
-
|
|
148
|
-
// Can we reset the counter?
|
|
149
|
-
if (
|
|
150
|
-
Date.now() >
|
|
151
|
-
this.lastRestart + MAX_RESTART_RESET_HOURS * 60 * 60 * 1000
|
|
152
|
-
) {
|
|
153
|
-
this.restartCounter = 0;
|
|
154
|
-
}
|
|
155
|
-
} else {
|
|
156
|
-
ActiveLogger.error(
|
|
157
|
-
"Not attempting to restart either due to signal or counters reached"
|
|
158
|
-
);
|
|
159
|
-
}
|
|
160
|
-
});
|
|
161
|
-
|
|
162
|
-
// Return running location
|
|
163
|
-
return "http://127.0.0.1:" + ActiveOptions.get<any>("db", {}).selfhost.port;
|
|
164
|
-
}
|
|
165
|
-
|
|
166
|
-
private async storePid(pid: number): Promise<void> {
|
|
167
|
-
const pidPath = ".PID";
|
|
168
|
-
let pidData: {
|
|
169
|
-
activeledger: number;
|
|
170
|
-
activestorage: number;
|
|
171
|
-
activecore: number;
|
|
172
|
-
activerestore: number;
|
|
173
|
-
};
|
|
174
|
-
|
|
175
|
-
try {
|
|
176
|
-
pidData = JSON.parse((await fsPromises.readFile(pidPath)).toString());
|
|
177
|
-
pidData.activestorage = pid;
|
|
178
|
-
|
|
179
|
-
await fsPromises.writeFile(pidPath, JSON.stringify(pidData));
|
|
180
|
-
} catch (error) {
|
|
181
|
-
ActiveLogger.warn(
|
|
182
|
-
"Error storing PID, activeledger --stop may not work correctly"
|
|
183
|
-
);
|
|
184
|
-
ActiveLogger.warn(error.message);
|
|
185
|
-
}
|
|
186
|
-
}
|
|
187
|
-
}
|
package/src/driver.ts
DELETED
|
@@ -1,18 +0,0 @@
|
|
|
1
|
-
import { LevelUpChain } from "levelup";
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* Abstract interface for Activeledger storage backends.
|
|
5
|
-
*/
|
|
6
|
-
export interface IStorageDriver {
|
|
7
|
-
get(key: string): Promise<Buffer>;
|
|
8
|
-
getMany(keys: string[]): Promise<Buffer[]>;
|
|
9
|
-
put(key: string, value: any): Promise<void>;
|
|
10
|
-
del(key: string): Promise<void>;
|
|
11
|
-
batch(): Promise<LevelUpChain<any, any>>;
|
|
12
|
-
createReadStream(options: any): any;
|
|
13
|
-
createValueStream(): any;
|
|
14
|
-
isOpen(): boolean;
|
|
15
|
-
open(): Promise<void>;
|
|
16
|
-
close(): Promise<void>;
|
|
17
|
-
compactRange?(start: string, end: string): Promise<void>;
|
|
18
|
-
}
|
package/src/drivers/leveldb.ts
DELETED
|
@@ -1,145 +0,0 @@
|
|
|
1
|
-
import { IStorageDriver } from "../driver";
|
|
2
|
-
import { LevelUpChain } from "levelup";
|
|
3
|
-
import { mkdirSync } from "fs";
|
|
4
|
-
import { ClassicLevel } from "classic-level";
|
|
5
|
-
import { Readable } from "stream";
|
|
6
|
-
|
|
7
|
-
export class LevelDBDriver implements IStorageDriver {
|
|
8
|
-
private db: any = null;
|
|
9
|
-
private opening: boolean = false;
|
|
10
|
-
|
|
11
|
-
constructor(private location: string, provider: string) {
|
|
12
|
-
mkdirSync(location, { recursive: true });
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
public async get(key: string): Promise<Buffer> {
|
|
16
|
-
const val = await this.db.get(key);
|
|
17
|
-
if (val === undefined) {
|
|
18
|
-
// classic-level resolves undefined for a missing key instead of
|
|
19
|
-
// throwing (unlike the older levelup/leveldown API) - callers
|
|
20
|
-
// (prepareForWrite() in particular) check error.notFound to detect
|
|
21
|
-
// a new document, so restore that convention here.
|
|
22
|
-
const err: any = new Error(`Key not found in database [${key}]`);
|
|
23
|
-
err.notFound = true;
|
|
24
|
-
err.code = "LEVEL_NOT_FOUND";
|
|
25
|
-
throw err;
|
|
26
|
-
}
|
|
27
|
-
return Buffer.isBuffer(val) ? val : Buffer.from(val);
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
public async getMany(keys: string[]): Promise<Buffer[]> {
|
|
31
|
-
const vals = await this.db.getMany(keys);
|
|
32
|
-
// classic-level resolves undefined per-key for anything missing from
|
|
33
|
-
// the batch (matching get()'s single-key behaviour) rather than
|
|
34
|
-
// throwing - callers (permissionsChecker's stream lookups in
|
|
35
|
-
// particular) request keys that legitimately don't always exist
|
|
36
|
-
// (e.g. an optional ":stream" companion document) and rely on
|
|
37
|
-
// getMany() simply omitting those, not on positional correspondence
|
|
38
|
-
// to the input keys, so filter rather than converting undefined and
|
|
39
|
-
// crashing the whole batch.
|
|
40
|
-
return vals
|
|
41
|
-
.filter((v: any) => v !== undefined)
|
|
42
|
-
.map((v: any) => Buffer.isBuffer(v) ? v : Buffer.from(v));
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
public async put(key: string, value: any): Promise<void> {
|
|
46
|
-
await this.db.put(key, value);
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
public async del(key: string): Promise<void> {
|
|
50
|
-
await this.db.del(key);
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
public async batch(): Promise<LevelUpChain<any, any>> {
|
|
54
|
-
if (!this.db || this.db.status !== 'open') {
|
|
55
|
-
await this.open();
|
|
56
|
-
}
|
|
57
|
-
return this.db.batch();
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
public createReadStream(options: any): any {
|
|
61
|
-
const iterator = this.db.iterator(options);
|
|
62
|
-
|
|
63
|
-
return new Readable({
|
|
64
|
-
objectMode: true,
|
|
65
|
-
async read() {
|
|
66
|
-
try {
|
|
67
|
-
const entry = await iterator.next();
|
|
68
|
-
if (entry) {
|
|
69
|
-
const val = entry[1];
|
|
70
|
-
this.push({ key: entry[0], value: Buffer.isBuffer(val) ? val : Buffer.from(val) });
|
|
71
|
-
} else {
|
|
72
|
-
this.push(null);
|
|
73
|
-
await iterator.close();
|
|
74
|
-
}
|
|
75
|
-
} catch (err) {
|
|
76
|
-
this.emit("error", err);
|
|
77
|
-
this.push(null);
|
|
78
|
-
}
|
|
79
|
-
},
|
|
80
|
-
async destroy(err: Error | null, callback: (error: Error | null) => void) {
|
|
81
|
-
await iterator.close();
|
|
82
|
-
callback(err);
|
|
83
|
-
}
|
|
84
|
-
});
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
// classic-level's values()/keys() return a modern async-iterable, not a
|
|
88
|
-
// classic Node Readable stream - levelme.ts's backup() needs .on("data"),
|
|
89
|
-
// so wrap it the same way createReadStream() wraps the kv iterator.
|
|
90
|
-
public createValueStream(): any {
|
|
91
|
-
const iterator = this.db.values();
|
|
92
|
-
|
|
93
|
-
return new Readable({
|
|
94
|
-
objectMode: true,
|
|
95
|
-
async read() {
|
|
96
|
-
try {
|
|
97
|
-
const val = await iterator.next();
|
|
98
|
-
if (val !== undefined) {
|
|
99
|
-
this.push(Buffer.isBuffer(val) ? val : Buffer.from(val));
|
|
100
|
-
} else {
|
|
101
|
-
this.push(null);
|
|
102
|
-
await iterator.close();
|
|
103
|
-
}
|
|
104
|
-
} catch (err) {
|
|
105
|
-
this.emit("error", err);
|
|
106
|
-
this.push(null);
|
|
107
|
-
}
|
|
108
|
-
},
|
|
109
|
-
async destroy(err: Error | null, callback: (error: Error | null) => void) {
|
|
110
|
-
await iterator.close();
|
|
111
|
-
callback(err);
|
|
112
|
-
}
|
|
113
|
-
});
|
|
114
|
-
}
|
|
115
|
-
|
|
116
|
-
public isOpen(): boolean {
|
|
117
|
-
return this.db?.status === 'open';
|
|
118
|
-
}
|
|
119
|
-
|
|
120
|
-
public async open(): Promise<void> {
|
|
121
|
-
if (this.db?.status !== 'open' && !this.opening) {
|
|
122
|
-
this.opening = true;
|
|
123
|
-
try {
|
|
124
|
-
this.db = new ClassicLevel(this.location, { valueEncoding: 'binary' });
|
|
125
|
-
await this.db.open();
|
|
126
|
-
} catch (e) {
|
|
127
|
-
// If opening fails, ensure the DB instance is cleared so it doesn't hold resources/locks
|
|
128
|
-
this.db = null;
|
|
129
|
-
throw e;
|
|
130
|
-
} finally {
|
|
131
|
-
this.opening = false;
|
|
132
|
-
}
|
|
133
|
-
}
|
|
134
|
-
}
|
|
135
|
-
|
|
136
|
-
public async close(): Promise<void> {
|
|
137
|
-
await this.db.close();
|
|
138
|
-
}
|
|
139
|
-
|
|
140
|
-
public async compactRange(start: string, end: string): Promise<void> {
|
|
141
|
-
if (typeof (this.db as any).compactRange === 'function') {
|
|
142
|
-
await (this.db as any).compactRange(start, end);
|
|
143
|
-
}
|
|
144
|
-
}
|
|
145
|
-
}
|
package/src/drivers/rocksdb.ts
DELETED
|
@@ -1,118 +0,0 @@
|
|
|
1
|
-
import { IStorageDriver } from "../driver";
|
|
2
|
-
import { LevelUpChain } from "levelup";
|
|
3
|
-
import { mkdirSync } from "fs";
|
|
4
|
-
const { RocksLevel } = require("@nxtedition/rocksdb");
|
|
5
|
-
|
|
6
|
-
export class RocksDBDriver implements IStorageDriver {
|
|
7
|
-
private db: any = null;
|
|
8
|
-
private opening: boolean = false;
|
|
9
|
-
|
|
10
|
-
constructor(private location: string, provider: string) {
|
|
11
|
-
mkdirSync(location, { recursive: true });
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
public async get(key: string): Promise<Buffer> {
|
|
15
|
-
const val = await this.db.get(key);
|
|
16
|
-
if (val === undefined) {
|
|
17
|
-
// abstract-level-based drivers resolve undefined for a missing key
|
|
18
|
-
// instead of throwing (unlike the older levelup/leveldown API) -
|
|
19
|
-
// callers (prepareForWrite() in particular) check error.notFound to
|
|
20
|
-
// detect a new document, so restore that convention here.
|
|
21
|
-
const err: any = new Error(`Key not found in database [${key}]`);
|
|
22
|
-
err.notFound = true;
|
|
23
|
-
err.code = "LEVEL_NOT_FOUND";
|
|
24
|
-
throw err;
|
|
25
|
-
}
|
|
26
|
-
return Buffer.isBuffer(val) ? val : Buffer.from(val);
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
public async getMany(keys: string[]): Promise<Buffer[]> {
|
|
30
|
-
const vals = await this.db.getMany(keys);
|
|
31
|
-
// See leveldb.ts's getMany() - same fix, same reasoning: abstract-level
|
|
32
|
-
// -based drivers resolve undefined per-key for a missing entry rather
|
|
33
|
-
// than throwing, and callers rely on getMany() omitting those, not on
|
|
34
|
-
// positional correspondence to the input keys.
|
|
35
|
-
return vals
|
|
36
|
-
.filter((v: any) => v !== undefined)
|
|
37
|
-
.map((v: any) => Buffer.isBuffer(v) ? v : Buffer.from(v));
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
public async put(key: string, value: any): Promise<void> {
|
|
41
|
-
await this.db.put(key, value);
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
public async del(key: string): Promise<void> {
|
|
45
|
-
await this.db.del(key);
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
public async batch(): Promise<LevelUpChain<any, any>> {
|
|
49
|
-
if (!this.db || this.db.status !== 'open') {
|
|
50
|
-
await this.open();
|
|
51
|
-
}
|
|
52
|
-
return this.db.batch();
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
public createReadStream(options: any): any {
|
|
56
|
-
const iterator = this.db.iterator(options);
|
|
57
|
-
const { Readable } = require("stream");
|
|
58
|
-
|
|
59
|
-
return new Readable({
|
|
60
|
-
objectMode: true,
|
|
61
|
-
async read() {
|
|
62
|
-
try {
|
|
63
|
-
const entry = await iterator.next();
|
|
64
|
-
if (entry) {
|
|
65
|
-
const val = entry[1];
|
|
66
|
-
this.push({ key: entry[0], value: Buffer.isBuffer(val) ? val : Buffer.from(val) });
|
|
67
|
-
} else {
|
|
68
|
-
this.push(null);
|
|
69
|
-
await iterator.close();
|
|
70
|
-
}
|
|
71
|
-
} catch (err) {
|
|
72
|
-
this.emit("error", err);
|
|
73
|
-
this.push(null);
|
|
74
|
-
}
|
|
75
|
-
},
|
|
76
|
-
async destroy(err: Error | null, callback: (error: Error | null) => void) {
|
|
77
|
-
await iterator.close();
|
|
78
|
-
callback(err);
|
|
79
|
-
}
|
|
80
|
-
});
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
public createValueStream(): any {
|
|
84
|
-
return this.db.values();
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
public isOpen(): boolean {
|
|
88
|
-
return this.db?.status === 'open';
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
public async open(): Promise<void> {
|
|
92
|
-
if (this.db?.status !== 'open' && !this.opening) {
|
|
93
|
-
this.opening = true;
|
|
94
|
-
try {
|
|
95
|
-
this.db = new RocksLevel(this.location, { valueEncoding: 'binary' });
|
|
96
|
-
await this.db.open();
|
|
97
|
-
} catch (e) {
|
|
98
|
-
// If opening fails, ensure the DB instance is cleared so it doesn't hold resources/locks
|
|
99
|
-
this.db = null;
|
|
100
|
-
throw e;
|
|
101
|
-
} finally {
|
|
102
|
-
this.opening = false;
|
|
103
|
-
}
|
|
104
|
-
}
|
|
105
|
-
}
|
|
106
|
-
|
|
107
|
-
public async close(): Promise<void> {
|
|
108
|
-
await this.db.close();
|
|
109
|
-
}
|
|
110
|
-
|
|
111
|
-
public async compactRange(start: string, end: string): Promise<void> {
|
|
112
|
-
// RocksLevel now handles compaction internally or via properties;
|
|
113
|
-
// for this driver we keep the API consistent.
|
|
114
|
-
if (typeof (this.db as any).compactRange === 'function') {
|
|
115
|
-
await (this.db as any).compactRange(start, end);
|
|
116
|
-
}
|
|
117
|
-
}
|
|
118
|
-
}
|
package/src/heartbeat.ts
DELETED
|
@@ -1,60 +0,0 @@
|
|
|
1
|
-
/*
|
|
2
|
-
* MIT License (MIT)
|
|
3
|
-
* Copyright (c) 2018 Activeledger
|
|
4
|
-
*
|
|
5
|
-
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
-
* of this software and associated documentation files (the "Software"), to deal
|
|
7
|
-
* in the Software without restriction, including without limitation the rights
|
|
8
|
-
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
-
* copies of the Software, and to permit persons to whom the Software is
|
|
10
|
-
* furnished to do so, subject to the following conditions:
|
|
11
|
-
*
|
|
12
|
-
* The above copyright notice and this permission notice shall be included in all
|
|
13
|
-
* copies or substantial portions of the Software.
|
|
14
|
-
*
|
|
15
|
-
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
-
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
-
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
-
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
-
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
-
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
-
* SOFTWARE.
|
|
22
|
-
*/
|
|
23
|
-
import { IActiveHttpResponse } from "@activeledger/httpd/lib/httpd";
|
|
24
|
-
|
|
25
|
-
/**
|
|
26
|
-
* Connection Heartbeat management
|
|
27
|
-
*
|
|
28
|
-
* @export
|
|
29
|
-
* @class HeartBeat
|
|
30
|
-
*/
|
|
31
|
-
export class HeartBeat {
|
|
32
|
-
/**
|
|
33
|
-
* Start & Maintain SSE Heartbeat
|
|
34
|
-
*
|
|
35
|
-
* @static
|
|
36
|
-
* @param {ServerResponse} response
|
|
37
|
-
* @returns {NodeJS.Timeout}
|
|
38
|
-
*/
|
|
39
|
-
public static Start(response: IActiveHttpResponse): NodeJS.Timeout {
|
|
40
|
-
return setInterval(() => {
|
|
41
|
-
if (response.writable) {
|
|
42
|
-
response.cork(() => {
|
|
43
|
-
response.write(":\n\n");
|
|
44
|
-
});
|
|
45
|
-
}
|
|
46
|
-
// Increase timeout with TCP keepalive enabled.
|
|
47
|
-
// Some connections still may timeout after long periods of inactivity
|
|
48
|
-
}, 10 * 60 * 1000);
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
/**
|
|
52
|
-
* Stop SSE Heartbeat
|
|
53
|
-
*
|
|
54
|
-
* @static
|
|
55
|
-
* @param {NodeJS.Timeout} interval
|
|
56
|
-
*/
|
|
57
|
-
public static Stop(interval: NodeJS.Timeout): void {
|
|
58
|
-
clearInterval(interval);
|
|
59
|
-
}
|
|
60
|
-
}
|
package/src/index.ts
DELETED
|
@@ -1,25 +0,0 @@
|
|
|
1
|
-
/*
|
|
2
|
-
* MIT License (MIT)
|
|
3
|
-
* Copyright (c) 2018 Activeledger
|
|
4
|
-
*
|
|
5
|
-
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
-
* of this software and associated documentation files (the "Software"), to deal
|
|
7
|
-
* in the Software without restriction, including without limitation the rights
|
|
8
|
-
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
-
* copies of the Software, and to permit persons to whom the Software is
|
|
10
|
-
* furnished to do so, subject to the following conditions:
|
|
11
|
-
*
|
|
12
|
-
* The above copyright notice and this permission notice shall be included in all
|
|
13
|
-
* copies or substantial portions of the Software.
|
|
14
|
-
*
|
|
15
|
-
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
-
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
-
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
-
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
-
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
-
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
-
* SOFTWARE.
|
|
22
|
-
*/
|
|
23
|
-
|
|
24
|
-
import { ActiveDataStore } from "./datastore";
|
|
25
|
-
export { ActiveDataStore };
|