offheap 0.1.0 → 0.2.0

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.
Files changed (30) hide show
  1. package/.github/workflows/CI.yml +22 -1
  2. package/Cargo.toml +2 -2
  3. package/artifacts/bindings-aarch64-apple-darwin/index.d.ts +37 -25
  4. package/artifacts/bindings-aarch64-apple-darwin/index.js +165 -295
  5. package/artifacts/bindings-aarch64-unknown-linux-musl/index.d.ts +42 -0
  6. package/artifacts/bindings-aarch64-unknown-linux-musl/index.js +186 -0
  7. package/artifacts/bindings-x86_64-apple-darwin/index.d.ts +37 -25
  8. package/artifacts/bindings-x86_64-apple-darwin/index.js +165 -295
  9. package/artifacts/bindings-x86_64-pc-windows-msvc/index.d.ts +42 -30
  10. package/artifacts/bindings-x86_64-pc-windows-msvc/index.js +186 -316
  11. package/artifacts/bindings-x86_64-unknown-linux-gnu/index.d.ts +37 -25
  12. package/artifacts/bindings-x86_64-unknown-linux-gnu/index.js +165 -295
  13. package/artifacts/bindings-x86_64-unknown-linux-musl/index.d.ts +42 -0
  14. package/artifacts/bindings-x86_64-unknown-linux-musl/index.js +186 -0
  15. package/benchmarks/crossover_bench.js +139 -0
  16. package/docs/.vitepress/config.js +35 -0
  17. package/docs/guide/api.md +216 -0
  18. package/docs/guide/architecture.md +58 -0
  19. package/docs/guide/benchmarks.md +48 -0
  20. package/docs/guide/getting-started.md +74 -0
  21. package/docs/index.md +23 -0
  22. package/index.d.ts +37 -25
  23. package/index.js +165 -295
  24. package/package.json +21 -12
  25. package/src/algorithms/arc.rs +123 -25
  26. package/src/algorithms/lru.rs +94 -12
  27. package/src/algorithms/mod.rs +4 -0
  28. package/src/algorithms/tinylfu.rs +98 -35
  29. package/src/cache.rs +289 -94
  30. package/tests/index.test.js +134 -7
@@ -0,0 +1,186 @@
1
+ const { Cache: NativeCache, CacheManager: NativeCacheManager } = require('./binding');
2
+
3
+ const activePromises = new Map();
4
+ const finalizer = new FinalizationRegistry((nativeCache) => {
5
+ try {
6
+ nativeCache.dispose();
7
+ } catch (e) {
8
+ // Ignore errors during GC finalization
9
+ }
10
+ });
11
+
12
+ class Cache {
13
+ constructor(nativeCache) {
14
+ this._native = nativeCache;
15
+ this._id = Math.random().toString(36).substring(2);
16
+ finalizer.register(this, nativeCache, this);
17
+ }
18
+
19
+ get(key) {
20
+ return this._native.get(key);
21
+ }
22
+
23
+ peek(key) {
24
+ return this._native.peek(key);
25
+ }
26
+
27
+ has(key) {
28
+ return this._native.has(key);
29
+ }
30
+
31
+ set(key, value, ttlMs) {
32
+ return this._native.set(key, value, ttlMs);
33
+ }
34
+
35
+ touch(key, ttlMs) {
36
+ return this._native.touch(key, ttlMs);
37
+ }
38
+
39
+ delete(key) {
40
+ return this._native.delete(key);
41
+ }
42
+
43
+ clear() {
44
+ this._native.clear();
45
+ }
46
+
47
+ stats() {
48
+ const rawStats = this._native.stats();
49
+ return {
50
+ hits: rawStats.hits,
51
+ misses: rawStats.misses,
52
+ capacity: rawStats.capacity,
53
+ size: rawStats.size,
54
+ bytesUsed: rawStats.bytesUsed,
55
+ };
56
+ }
57
+
58
+ keys() {
59
+ return this._native.keys();
60
+ }
61
+
62
+ increment(key, delta = 1, ttlMs) {
63
+ return this._native.increment(key, delta, ttlMs);
64
+ }
65
+
66
+ decrement(key, delta = 1, ttlMs) {
67
+ return this._native.decrement(key, delta, ttlMs);
68
+ }
69
+
70
+ mget(keys) {
71
+ return this._native.mget(keys);
72
+ }
73
+
74
+ mset(entries, ttlMs) {
75
+ if (typeof entries !== 'object' || entries === null) {
76
+ throw new Error('mset requires an object of key-value entries');
77
+ }
78
+ this._native.mset(entries, ttlMs);
79
+ }
80
+
81
+ mdelete(keys) {
82
+ if (!Array.isArray(keys)) {
83
+ throw new Error('mdelete requires an array of keys');
84
+ }
85
+ return this._native.mdelete(keys);
86
+ }
87
+
88
+ dispose() {
89
+ finalizer.unregister(this);
90
+ this._native.dispose();
91
+ }
92
+
93
+ getOrSet(key, factory, ttlMs) {
94
+ const val = this.get(key);
95
+ if (val !== undefined) {
96
+ return val;
97
+ }
98
+
99
+ const promiseKey = `${this._id}:${key}`;
100
+ if (activePromises.has(promiseKey)) {
101
+ return activePromises.get(promiseKey);
102
+ }
103
+
104
+ try {
105
+ const res = factory();
106
+ if (res instanceof Promise) {
107
+ const p = res
108
+ .then((resolvedVal) => {
109
+ activePromises.delete(promiseKey);
110
+ if (resolvedVal !== undefined) {
111
+ this.set(key, resolvedVal, ttlMs);
112
+ }
113
+ return resolvedVal;
114
+ })
115
+ .catch((err) => {
116
+ activePromises.delete(promiseKey);
117
+ throw err;
118
+ });
119
+ activePromises.set(promiseKey, p);
120
+ return p;
121
+ } else {
122
+ if (res !== undefined) {
123
+ this.set(key, res, ttlMs);
124
+ }
125
+ return res;
126
+ }
127
+ } catch (err) {
128
+ activePromises.delete(promiseKey);
129
+ throw err;
130
+ }
131
+ }
132
+ }
133
+
134
+ const activeManagers = new Set();
135
+
136
+ class CacheManager {
137
+ constructor() {
138
+ this._native = new NativeCacheManager();
139
+ activeManagers.add(this);
140
+ }
141
+
142
+ createCache(name, config) {
143
+ const rawConfig = {
144
+ policy: config.policy,
145
+ capacity: config.capacity,
146
+ shards: config.shards,
147
+ maxBytes: config.maxBytes,
148
+ };
149
+ const nativeCache = this._native.createCache(name, rawConfig);
150
+ return new Cache(nativeCache);
151
+ }
152
+
153
+ getCache(name) {
154
+ const nativeCache = this._native.getCache(name);
155
+ if (!nativeCache) return null;
156
+ return new Cache(nativeCache);
157
+ }
158
+
159
+ deleteCache(name) {
160
+ return this._native.deleteCache(name);
161
+ }
162
+
163
+ clear() {
164
+ this._native.clear();
165
+ }
166
+
167
+ dispose() {
168
+ activeManagers.delete(this);
169
+ this._native.clear();
170
+ }
171
+ }
172
+
173
+ process.on('exit', () => {
174
+ for (const manager of activeManagers) {
175
+ try {
176
+ manager.dispose();
177
+ } catch (e) {
178
+ // Ignore cleanup failures on process exit
179
+ }
180
+ }
181
+ });
182
+
183
+ module.exports = {
184
+ Cache,
185
+ CacheManager,
186
+ };
@@ -1,30 +1,42 @@
1
- /* tslint:disable */
2
- /* eslint-disable */
3
-
4
- /* auto-generated by NAPI-RS */
5
-
6
1
  export interface CacheConfig {
7
- policy: string
8
- capacity: number
2
+ policy: 'lru' | 'arc' | 'tinylfu';
3
+ capacity: number;
4
+ shards?: number;
5
+ maxBytes?: number;
9
6
  }
10
- export interface CacheStatsJs {
11
- hits: number
12
- misses: number
13
- capacity: number
14
- size: number
7
+
8
+ export interface CacheStats {
9
+ hits: number;
10
+ misses: number;
11
+ capacity: number;
12
+ size: number;
13
+ bytesUsed: number;
15
14
  }
16
- export declare class Cache {
17
- get(key: string): unknown
18
- set(key: string, value: unknown, ttlMs?: number | undefined | null): unknown
19
- delete(key: string): boolean
20
- clear(): void
21
- stats(): CacheStatsJs
22
- keys(): Array<string>
15
+
16
+ export class Cache {
17
+ get<T = any>(key: string): T | undefined;
18
+ peek<T = any>(key: string): T | undefined;
19
+ has(key: string): boolean;
20
+ set<T = any>(key: string, value: T, ttlMs?: number): T | undefined;
21
+ touch(key: string, ttlMs?: number): boolean;
22
+ delete(key: string): boolean;
23
+ clear(): void;
24
+ stats(): CacheStats;
25
+ keys(): string[];
26
+ increment(key: string, delta?: number, ttlMs?: number): number;
27
+ decrement(key: string, delta?: number, ttlMs?: number): number;
28
+ mget(keys: string[]): Record<string, any>;
29
+ mset(entries: Record<string, any>, ttlMs?: number): void;
30
+ mdelete(keys: string[]): number;
31
+ dispose(): void;
32
+ getOrSet<T = any>(key: string, factory: () => T | Promise<T>, ttlMs?: number): T | Promise<T>;
23
33
  }
24
- export declare class CacheManager {
25
- constructor()
26
- createCache(name: string, config: CacheConfig): Cache
27
- getCache(name: string): Cache | null
28
- deleteCache(name: string): boolean
29
- clear(): void
34
+
35
+ export class CacheManager {
36
+ constructor();
37
+ createCache(name: string, config: CacheConfig): Cache;
38
+ getCache(name: string): Cache | null;
39
+ deleteCache(name: string): boolean;
40
+ clear(): void;
41
+ dispose(): void;
30
42
  }