@rsdk/nats.kv 5.4.0-next.4 → 5.4.0-next.6

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/CHANGELOG.md CHANGED
@@ -3,6 +3,16 @@
3
3
  All notable changes to this project will be documented in this file.
4
4
  See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
5
5
 
6
+ ## [5.4.0-next.6](https://github.com/R-Vision/rsdk/compare/v5.4.0-next.5...v5.4.0-next.6) (2024-11-28)
7
+
8
+ **Note:** Version bump only for package @rsdk/nats.kv
9
+
10
+ ## [5.4.0-next.5](https://github.com/R-Vision/rsdk/compare/v5.4.0-next.4...v5.4.0-next.5) (2024-11-28)
11
+
12
+ ### Features
13
+
14
+ * get meta for kv entry ([#309](https://github.com/R-Vision/rsdk/issues/309)) ([ff8c39d](https://github.com/R-Vision/rsdk/commit/ff8c39d2cc072230931023c9d1e2cef716fa3eaf))
15
+
6
16
  ## [5.4.0-next.4](https://github.com/R-Vision/rsdk/compare/v5.4.0-next.3...v5.4.0-next.4) (2024-11-27)
7
17
 
8
18
  ### Bug Fixes
@@ -1,15 +1,25 @@
1
1
  import type { ILogger } from '@rsdk/logging';
2
- import type { KV, KvDeleteOptions, KvEntry, KvPutOptions, KvStatus, Payload } from 'nats';
2
+ import type { KV, KvDeleteOptions, KvPutOptions, KvStatus, NatsConnection, Payload } from 'nats';
3
3
  import type { NatsKvEntry } from './interfaces/nats-kv-entry.interface';
4
+ import type { NatsKvEntryMeta } from './interfaces/nats-kv-entry-meta.interface';
4
5
  import type { DecodeFunc } from './types/decode-func.type';
5
6
  export declare class KvStorage {
6
7
  private readonly storage;
7
8
  private readonly logger;
8
- constructor(storage: KV, logger: ILogger);
9
+ private readonly bucketName;
10
+ private readonly connection;
11
+ constructor(storage: KV, logger: ILogger, bucketName: string, connection: NatsConnection);
9
12
  getKeys(filter?: string | string[]): Promise<string[]>;
10
13
  getAllWithMeta<Decode extends DecodeFunc>(decode: Decode, filter?: string | string[]): Promise<NatsKvEntry<Decode>[]>;
11
14
  get<Decode extends DecodeFunc>(key: string, decode: Decode): Promise<ReturnType<Decode> | null>;
12
- getWithMeta(key: string): Promise<KvEntry | null>;
15
+ getWithMeta<Decode extends DecodeFunc>(key: string, decode: Decode): Promise<NatsKvEntry<Decode> | null>;
16
+ /**
17
+ * Получает мета-информацию о ключе в хранилище KV (без данных).
18
+ *
19
+ * @param {string} key - Ключ, для которого необходимо получить мета-информацию.
20
+ * @returns {Promise<NatsKvEntryMeta | null>} Объект метаданных (NatsKvEntryMeta), если данные найдены, или `null`, если данные отсутствуют.
21
+ */
22
+ getMeta(key: string): Promise<NatsKvEntryMeta | null>;
13
23
  getAll<Decode extends DecodeFunc>(decode: Decode, filter?: string | string[]): Promise<ReturnType<Decode>[]>;
14
24
  status(): Promise<KvStatus>;
15
25
  put(key: string, data: Payload, opts?: Partial<KvPutOptions>): Promise<number>;
@@ -20,4 +30,5 @@ export declare class KvStorage {
20
30
  * для безопасного взаимодействия.
21
31
  */
22
32
  getRawStorage(): KV;
33
+ private createMeta;
23
34
  }
@@ -1,12 +1,17 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.KvStorage = void 0;
4
+ const nats_1 = require("nats");
4
5
  class KvStorage {
5
6
  storage;
6
7
  logger;
7
- constructor(storage, logger) {
8
+ bucketName;
9
+ connection;
10
+ constructor(storage, logger, bucketName, connection) {
8
11
  this.storage = storage;
9
12
  this.logger = logger;
13
+ this.bucketName = bucketName;
14
+ this.connection = connection;
10
15
  }
11
16
  async getKeys(filter) {
12
17
  const keysIterator = await this.storage.keys(filter);
@@ -32,12 +37,7 @@ class KvStorage {
32
37
  }
33
38
  result.push({
34
39
  data: decode(entry.value),
35
- meta: {
36
- created: entry.created,
37
- length: entry.length,
38
- operation: entry.operation,
39
- revision: entry.revision,
40
- },
40
+ meta: this.createMeta(entry),
41
41
  });
42
42
  }
43
43
  this.logger.trace('Getting all entries from KV: KV entries received', {
@@ -46,13 +46,47 @@ class KvStorage {
46
46
  return result;
47
47
  }
48
48
  async get(key, decode) {
49
- const entry = await this.getWithMeta(key);
49
+ const entry = await this.getWithMeta(key, decode);
50
+ return entry?.data ?? null;
51
+ }
52
+ async getWithMeta(key, decode) {
53
+ const entry = await this.storage.get(key);
50
54
  if (!entry)
51
55
  return null;
52
- return decode(entry.value);
56
+ return {
57
+ data: decode(entry.value),
58
+ meta: this.createMeta(entry),
59
+ };
53
60
  }
54
- async getWithMeta(key) {
55
- return this.storage.get(key);
61
+ /**
62
+ * Получает мета-информацию о ключе в хранилище KV (без данных).
63
+ *
64
+ * @param {string} key - Ключ, для которого необходимо получить мета-информацию.
65
+ * @returns {Promise<NatsKvEntryMeta | null>} Объект метаданных (NatsKvEntryMeta), если данные найдены, или `null`, если данные отсутствуют.
66
+ */
67
+ async getMeta(key) {
68
+ // HACK: данный костыль с JetStream необходим из-за отсутствия в библиотеке функции получения меты без данных
69
+ const streamName = `KV_${this.bucketName}`;
70
+ const subject = `$KV.${this.bucketName}.${key}`;
71
+ const consumer = await this.connection
72
+ .jetstream()
73
+ .consumers.get(streamName, {
74
+ headers_only: true,
75
+ filterSubjects: subject,
76
+ deliver_policy: nats_1.DeliverPolicy.LastPerSubject,
77
+ });
78
+ const msgs = await consumer.fetch({ max_messages: 1, expires: 1000 });
79
+ for await (const msg of msgs) {
80
+ msg.ack();
81
+ return {
82
+ created: new Date((0, nats_1.millis)(msg.info.timestampNanos)),
83
+ length: +(msg.headers?.get('Nats-Msg-Size') || '0'),
84
+ operation: msg.headers?.get('KV-Operation') ||
85
+ 'PUT',
86
+ revision: msg.info.streamSequence,
87
+ };
88
+ }
89
+ return null;
56
90
  }
57
91
  async getAll(decode, filter) {
58
92
  const entries = await this.getAllWithMeta(decode, filter);
@@ -75,6 +109,14 @@ class KvStorage {
75
109
  getRawStorage() {
76
110
  return this.storage;
77
111
  }
112
+ createMeta(entry) {
113
+ return {
114
+ created: entry.created,
115
+ length: entry.length,
116
+ operation: entry.operation,
117
+ revision: entry.revision,
118
+ };
119
+ }
78
120
  }
79
121
  exports.KvStorage = KvStorage;
80
122
  //# sourceMappingURL=kv-storage.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"kv-storage.js","sourceRoot":"","sources":["../src/kv-storage.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"kv-storage.js","sourceRoot":"","sources":["../src/kv-storage.ts"],"names":[],"mappings":"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"}
@@ -41,7 +41,7 @@ let NatsKvService = class NatsKvService {
41
41
  connectionName: this.nats.info,
42
42
  bucketName,
43
43
  });
44
- return new kv_storage_1.KvStorage(kv, this.logger);
44
+ return new kv_storage_1.KvStorage(kv, this.logger, bucketName, this.nats);
45
45
  }
46
46
  catch (error) {
47
47
  this.logger.error('Failed to get or create KV store', {
@@ -1 +1 @@
1
- {"version":3,"file":"nats-kv.service.js","sourceRoot":"","sources":["../src/nats-kv.service.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"nats-kv.service.js","sourceRoot":"","sources":["../src/nats-kv.service.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rsdk/nats.kv",
3
- "version": "5.4.0-next.4",
3
+ "version": "5.4.0-next.6",
4
4
  "description": "Nats NestJS key-Value storage",
5
5
  "main": "dist/index.js",
6
6
  "license": "Apache License 2.0",
@@ -14,10 +14,10 @@
14
14
  "@nestjs-plugins/nestjs-nats-jetstream-transport": "^2.2.6",
15
15
  "lodash": "^4.17.21",
16
16
  "nats": "^2.28.0",
17
- "typescript": "^5.3.2"
17
+ "typescript": "5.5.4"
18
18
  },
19
19
  "peerDependencies": {
20
- "@grpc/grpc-js": "^1.10.9",
20
+ "@grpc/grpc-js": "^1.10.11",
21
21
  "@nestjs/common": "^10.0.0",
22
22
  "@nestjs/config": "^3.2.3",
23
23
  "@nestjs/core": "^10.0.0",
@@ -38,5 +38,5 @@
38
38
  "rxjs": "^7.8.1"
39
39
  },
40
40
  "nx": {},
41
- "gitHead": "6f7d6802d4dc34620f3c0e8c8ec73887df36a647"
41
+ "gitHead": "acc1405be758b5ba4d2e8eda8d34b3c4f60a813f"
42
42
  }
package/src/kv-storage.ts CHANGED
@@ -5,16 +5,21 @@ import type {
5
5
  KvEntry,
6
6
  KvPutOptions,
7
7
  KvStatus,
8
+ NatsConnection,
8
9
  Payload,
9
10
  } from 'nats';
11
+ import { DeliverPolicy, millis } from 'nats';
10
12
 
11
13
  import type { NatsKvEntry } from './interfaces/nats-kv-entry.interface';
14
+ import type { NatsKvEntryMeta } from './interfaces/nats-kv-entry-meta.interface';
12
15
  import type { DecodeFunc } from './types/decode-func.type';
13
16
 
14
17
  export class KvStorage {
15
18
  constructor(
16
19
  private readonly storage: KV,
17
20
  private readonly logger: ILogger,
21
+ private readonly bucketName: string,
22
+ private readonly connection: NatsConnection,
18
23
  ) {}
19
24
 
20
25
  public async getKeys(filter?: string | string[]): Promise<string[]> {
@@ -51,12 +56,7 @@ export class KvStorage {
51
56
 
52
57
  result.push({
53
58
  data: decode(entry.value),
54
- meta: {
55
- created: entry.created,
56
- length: entry.length,
57
- operation: entry.operation,
58
- revision: entry.revision,
59
- },
59
+ meta: this.createMeta(entry),
60
60
  });
61
61
  }
62
62
 
@@ -71,15 +71,60 @@ export class KvStorage {
71
71
  key: string,
72
72
  decode: Decode,
73
73
  ): Promise<ReturnType<Decode> | null> {
74
- const entry = await this.getWithMeta(key);
74
+ const entry = await this.getWithMeta(key, decode);
75
+
76
+ return entry?.data ?? null;
77
+ }
78
+
79
+ public async getWithMeta<Decode extends DecodeFunc>(
80
+ key: string,
81
+ decode: Decode,
82
+ ): Promise<NatsKvEntry<Decode> | null> {
83
+ const entry = await this.storage.get(key);
75
84
 
76
85
  if (!entry) return null;
77
86
 
78
- return decode(entry.value);
87
+ return {
88
+ data: decode(entry.value),
89
+ meta: this.createMeta(entry),
90
+ };
79
91
  }
80
92
 
81
- public async getWithMeta(key: string): Promise<KvEntry | null> {
82
- return this.storage.get(key);
93
+ /**
94
+ * Получает мета-информацию о ключе в хранилище KV (без данных).
95
+ *
96
+ * @param {string} key - Ключ, для которого необходимо получить мета-информацию.
97
+ * @returns {Promise<NatsKvEntryMeta | null>} Объект метаданных (NatsKvEntryMeta), если данные найдены, или `null`, если данные отсутствуют.
98
+ */
99
+ public async getMeta(key: string): Promise<NatsKvEntryMeta | null> {
100
+ // HACK: данный костыль с JetStream необходим из-за отсутствия в библиотеке функции получения меты без данных
101
+ const streamName = `KV_${this.bucketName}`;
102
+ const subject = `$KV.${this.bucketName}.${key}`;
103
+
104
+ const consumer = await this.connection
105
+ .jetstream()
106
+ .consumers.get(streamName, {
107
+ headers_only: true,
108
+ filterSubjects: subject,
109
+ deliver_policy: DeliverPolicy.LastPerSubject,
110
+ });
111
+
112
+ const msgs = await consumer.fetch({ max_messages: 1, expires: 1000 });
113
+
114
+ for await (const msg of msgs) {
115
+ msg.ack();
116
+
117
+ return {
118
+ created: new Date(millis(msg.info.timestampNanos)),
119
+ length: +(msg.headers?.get('Nats-Msg-Size') || '0'),
120
+ operation:
121
+ (msg.headers?.get('KV-Operation') as 'PUT' | 'DEL' | 'PURGE') ||
122
+ 'PUT',
123
+ revision: msg.info.streamSequence,
124
+ };
125
+ }
126
+
127
+ return null;
83
128
  }
84
129
 
85
130
  public async getAll<Decode extends DecodeFunc>(
@@ -118,4 +163,13 @@ export class KvStorage {
118
163
  public getRawStorage(): KV {
119
164
  return this.storage;
120
165
  }
166
+
167
+ private createMeta(entry: KvEntry): NatsKvEntryMeta {
168
+ return {
169
+ created: entry.created,
170
+ length: entry.length,
171
+ operation: entry.operation,
172
+ revision: entry.revision,
173
+ };
174
+ }
121
175
  }
@@ -44,7 +44,7 @@ export class NatsKvService {
44
44
  bucketName,
45
45
  });
46
46
 
47
- return new KvStorage(kv, this.logger);
47
+ return new KvStorage(kv, this.logger, bucketName, this.nats);
48
48
  } catch (error) {
49
49
  this.logger.error('Failed to get or create KV store', {
50
50
  err: error,