@omnitronix/rng-client-core 1.0.10 → 1.1.2

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 (88) hide show
  1. package/dist/core/rng-client-core.d.ts +0 -1
  2. package/dist/core/rng-client-core.js +1 -1
  3. package/dist/errors/rng-errors.d.ts +0 -1
  4. package/dist/errors/rng-errors.js +1 -1
  5. package/dist/grpc/grpc-rng-client.d.ts +0 -1
  6. package/dist/grpc/grpc-rng-client.js +1 -1
  7. package/dist/grpc/grpc-rng-interface.d.ts +0 -1
  8. package/dist/grpc/grpc-rng-interface.js +1 -1
  9. package/dist/http/http-client.types.d.ts +0 -1
  10. package/dist/http/http-client.types.js +1 -1
  11. package/dist/http/http-rng-client.d.ts +0 -1
  12. package/dist/http/http-rng-client.js +1 -1
  13. package/dist/http/rest-client.d.ts +0 -1
  14. package/dist/http/rest-client.js +1 -1
  15. package/dist/http/rng-client.interface.d.ts +0 -1
  16. package/dist/http/rng-client.interface.js +1 -1
  17. package/dist/index.d.ts +6 -6
  18. package/dist/index.js +1 -1
  19. package/dist/interfaces/client-interfaces.d.ts +6 -3
  20. package/dist/interfaces/client-interfaces.js +1 -1
  21. package/dist/interfaces/metrics.d.ts +30 -0
  22. package/dist/interfaces/metrics.js +3 -0
  23. package/dist/metrics/default-metrics-handlers.d.ts +2 -0
  24. package/dist/metrics/default-metrics-handlers.js +23 -0
  25. package/dist/ring-buffer/interfaces.d.ts +0 -38
  26. package/dist/ring-buffer/interfaces.js +1 -1
  27. package/dist/ring-buffer/ring-buffer.d.ts +7 -14
  28. package/dist/ring-buffer/ring-buffer.js +63 -207
  29. package/dist/ring-buffer/ring-storage-memory.d.ts +1 -3
  30. package/dist/ring-buffer/ring-storage-memory.js +1 -25
  31. package/dist/ring-buffer/ring-storage.d.ts +1 -3
  32. package/dist/ring-buffer/ring-storage.js +1 -7
  33. package/dist/rng-client.d.ts +2 -5
  34. package/dist/rng-client.js +6 -4
  35. package/package.json +3 -2
  36. package/src/__tests__/grpc-rng-client.test.ts +167 -0
  37. package/src/__tests__/rng-client-core.integration.test.ts +117 -0
  38. package/src/__tests__/rng-client-core.test.ts +249 -0
  39. package/src/__tests__/rng-client-grpc.test.ts +324 -0
  40. package/src/__tests__/rng-client.test.ts +296 -0
  41. package/src/core/rng-client-core.ts +80 -0
  42. package/src/errors/rng-errors.ts +96 -0
  43. package/src/grpc/grpc-rng-client.ts +162 -0
  44. package/src/grpc/grpc-rng-interface.ts +36 -0
  45. package/src/http/http-client.types.ts +48 -0
  46. package/src/http/http-rng-client.ts +140 -0
  47. package/src/http/rest-client.ts +151 -0
  48. package/src/http/rng-client.interface.ts +22 -0
  49. package/src/index.ts +21 -0
  50. package/src/interfaces/client-interfaces.ts +15 -0
  51. package/src/interfaces/metrics.ts +38 -0
  52. package/src/metrics/default-metrics-handlers.ts +29 -0
  53. package/src/ring-buffer/interfaces.ts +9 -0
  54. package/src/ring-buffer/ring-buffer.ts +214 -0
  55. package/src/ring-buffer/ring-storage-memory.ts +48 -0
  56. package/src/ring-buffer/ring-storage.ts +59 -0
  57. package/src/rng-client.ts +190 -0
  58. package/src/rng.proto +102 -0
  59. package/dist/core/rng-client-core.d.ts.map +0 -1
  60. package/dist/core/rng-client-core.js.map +0 -1
  61. package/dist/errors/rng-errors.d.ts.map +0 -1
  62. package/dist/errors/rng-errors.js.map +0 -1
  63. package/dist/grpc/grpc-rng-client.d.ts.map +0 -1
  64. package/dist/grpc/grpc-rng-client.js.map +0 -1
  65. package/dist/grpc/grpc-rng-interface.d.ts.map +0 -1
  66. package/dist/grpc/grpc-rng-interface.js.map +0 -1
  67. package/dist/http/http-client.types.d.ts.map +0 -1
  68. package/dist/http/http-client.types.js.map +0 -1
  69. package/dist/http/http-rng-client.d.ts.map +0 -1
  70. package/dist/http/http-rng-client.js.map +0 -1
  71. package/dist/http/rest-client.d.ts.map +0 -1
  72. package/dist/http/rest-client.js.map +0 -1
  73. package/dist/http/rng-client.interface.d.ts.map +0 -1
  74. package/dist/http/rng-client.interface.js.map +0 -1
  75. package/dist/index.d.ts.map +0 -1
  76. package/dist/index.js.map +0 -1
  77. package/dist/interfaces/client-interfaces.d.ts.map +0 -1
  78. package/dist/interfaces/client-interfaces.js.map +0 -1
  79. package/dist/ring-buffer/interfaces.d.ts.map +0 -1
  80. package/dist/ring-buffer/interfaces.js.map +0 -1
  81. package/dist/ring-buffer/ring-buffer.d.ts.map +0 -1
  82. package/dist/ring-buffer/ring-buffer.js.map +0 -1
  83. package/dist/ring-buffer/ring-storage-memory.d.ts.map +0 -1
  84. package/dist/ring-buffer/ring-storage-memory.js.map +0 -1
  85. package/dist/ring-buffer/ring-storage.d.ts.map +0 -1
  86. package/dist/ring-buffer/ring-storage.js.map +0 -1
  87. package/dist/rng-client.d.ts.map +0 -1
  88. package/dist/rng-client.js.map +0 -1
@@ -0,0 +1,38 @@
1
+ export interface Counter<L = Record<string, string | number>> {
2
+ inc: (_labels?: L, _value?: number) => void;
3
+ }
4
+
5
+ export interface Histogram<L = Record<string, string | number>> {
6
+ observe: (_labels: L, _value: number) => void;
7
+ }
8
+
9
+ export interface Gauge<L = Record<string, string | number>> {
10
+ set: (_labels: L, _value: number) => void;
11
+ }
12
+
13
+ interface RngBufferBaseLabels {
14
+ rng_range: string;
15
+ engine_type: string;
16
+ }
17
+
18
+ export interface RngBufferMetricsHandlers {
19
+ rngBufferCapacity: Gauge<RngBufferBaseLabels>;
20
+ rngBufferFillLevel: Gauge<RngBufferBaseLabels>;
21
+ rngBufferFillRatio: Gauge<RngBufferBaseLabels>;
22
+ rngBufferRefillRequestsTotal: Counter<
23
+ RngBufferBaseLabels & {
24
+ reason?: string;
25
+ }
26
+ >;
27
+ rngBufferRefillFailuresTotal: Counter<
28
+ RngBufferBaseLabels & {
29
+ reason?: string;
30
+ error?: string;
31
+ }
32
+ >;
33
+ rngBufferRefillDurationMs: Histogram<RngBufferBaseLabels>;
34
+ rngBufferStarvationEventsTotal: Counter<RngBufferBaseLabels>;
35
+ rngBufferLatencyMs: Histogram<RngBufferBaseLabels>;
36
+ }
37
+
38
+ export type RngClientMetricsHandlers = RngBufferMetricsHandlers;
@@ -0,0 +1,29 @@
1
+ import {
2
+ Counter,
3
+ Gauge,
4
+ Histogram,
5
+ RngClientMetricsHandlers,
6
+ } from '../interfaces/metrics';
7
+
8
+ class DummyCounter implements Counter {
9
+ inc(_labels?: unknown, _value?: number): void {}
10
+ }
11
+
12
+ class DummyGauge implements Gauge {
13
+ set(_labels: unknown, _value: number): void {}
14
+ }
15
+
16
+ class DummyHistogram implements Histogram {
17
+ observe(_labels: unknown, _value: number): void {}
18
+ }
19
+
20
+ export const defaultMetricsHandlers: RngClientMetricsHandlers = {
21
+ rngBufferCapacity: new DummyGauge(),
22
+ rngBufferFillLevel: new DummyGauge(),
23
+ rngBufferFillRatio: new DummyGauge(),
24
+ rngBufferRefillRequestsTotal: new DummyCounter(),
25
+ rngBufferRefillFailuresTotal: new DummyCounter(),
26
+ rngBufferRefillDurationMs: new DummyHistogram(),
27
+ rngBufferStarvationEventsTotal: new DummyCounter(),
28
+ rngBufferLatencyMs: new DummyHistogram(),
29
+ };
@@ -0,0 +1,9 @@
1
+ export interface SingleRingBuffer {
2
+ items: RingBufferValue[];
3
+ range: { min: number; max: number };
4
+ }
5
+
6
+ export interface RingBufferValue {
7
+ value: number;
8
+ seed: number;
9
+ }
@@ -0,0 +1,214 @@
1
+ import { RingBufferValue, SingleRingBuffer } from './interfaces';
2
+ import { RngClientCore } from '../core/rng-client-core';
3
+ import { RingStorage, StorageType } from './ring-storage';
4
+ import { RngBufferMetricsHandlers } from '../interfaces/metrics';
5
+
6
+ export const FILL_UP_BUFFER_DELAY = 5;
7
+
8
+ export interface RingBufferConfig {
9
+ size?: number;
10
+ clientCore: RngClientCore;
11
+ storageType: StorageType;
12
+ metrics: RngBufferMetricsHandlers;
13
+ }
14
+
15
+ export class RingBuffer {
16
+ private size: number;
17
+ private maxSize: number;
18
+ private clientCore: RngClientCore;
19
+ private storageType: StorageType;
20
+ private storage: RingStorage;
21
+ private readonly metrics: RngBufferMetricsHandlers;
22
+
23
+ constructor({ size, clientCore, storageType, metrics }: RingBufferConfig) {
24
+ this.size = size ?? 2000;
25
+ this.maxSize = this.size * 2;
26
+ this.clientCore = clientCore;
27
+ this.storageType = storageType;
28
+ this.storage = new RingStorage(storageType);
29
+ this.metrics = metrics;
30
+ }
31
+
32
+ private getRangeKey(min: number, max: number): string {
33
+ return `${min}-${max}`;
34
+ }
35
+
36
+ private getEngineType(): string {
37
+ return 'default';
38
+ }
39
+
40
+ async getNumbersByRange(
41
+ min: number,
42
+ max: number,
43
+ count = 1
44
+ ): Promise<RingBufferValue[] | undefined> {
45
+ const rangeKey = this.getRangeKey(min, max);
46
+ let requestStartTime = Date.now();
47
+
48
+ const buffer = await this.storage.getBufferByRange(min, max);
49
+ if (!buffer) {
50
+ this.metrics.rngBufferStarvationEventsTotal.inc({
51
+ rng_range: rangeKey,
52
+ engine_type: this.getEngineType(),
53
+ });
54
+
55
+ const newBuffer = this.createBuffer(min, max);
56
+ await this.storage.saveBuffer(newBuffer);
57
+ setTimeout(async () => {
58
+ requestStartTime = Date.now();
59
+ await this.fillUpBuffer(newBuffer, 'initial');
60
+ const latency = Date.now() - requestStartTime;
61
+ this.metrics.rngBufferLatencyMs.observe(
62
+ {
63
+ rng_range: rangeKey,
64
+ engine_type: this.getEngineType(),
65
+ },
66
+ latency
67
+ );
68
+ }, FILL_UP_BUFFER_DELAY);
69
+
70
+ return undefined;
71
+ }
72
+
73
+ const item = await this.storage.getFromBuffer(buffer, count);
74
+ if (!item) {
75
+ this.metrics.rngBufferStarvationEventsTotal.inc({
76
+ rng_range: rangeKey,
77
+ engine_type: this.getEngineType(),
78
+ });
79
+
80
+ setTimeout(async () => {
81
+ requestStartTime = Date.now();
82
+ await this.fillUpBuffer(buffer, 'starvation');
83
+ const latency = Date.now() - requestStartTime;
84
+ this.metrics.rngBufferLatencyMs.observe(
85
+ {
86
+ rng_range: rangeKey,
87
+ engine_type: this.getEngineType(),
88
+ },
89
+ latency
90
+ );
91
+ }, FILL_UP_BUFFER_DELAY);
92
+
93
+ return undefined;
94
+ }
95
+
96
+ setTimeout(async () => {
97
+ requestStartTime = Date.now();
98
+ await this.fillUpBuffer(buffer, 'refill');
99
+ const latency = Date.now() - requestStartTime;
100
+ this.metrics.rngBufferLatencyMs.observe(
101
+ {
102
+ rng_range: rangeKey,
103
+ engine_type: this.getEngineType(),
104
+ },
105
+ latency
106
+ );
107
+ }, FILL_UP_BUFFER_DELAY);
108
+
109
+ return item;
110
+ }
111
+
112
+ async fillUpBuffer(
113
+ buffer: SingleRingBuffer,
114
+ reason: string = 'scheduled'
115
+ ): Promise<void> {
116
+ const rangeKey = this.getRangeKey(buffer.range.min, buffer.range.max);
117
+ const refillStartTime = Date.now();
118
+
119
+ this.metrics.rngBufferRefillRequestsTotal.inc({
120
+ rng_range: rangeKey,
121
+ engine_type: this.getEngineType(),
122
+ reason,
123
+ });
124
+
125
+ try {
126
+ const values = await this.pullNumberByBuffer(buffer);
127
+ if (values.length === 0 || buffer.items.length >= this.maxSize) {
128
+ const duration = Date.now() - refillStartTime;
129
+ this.metrics.rngBufferRefillDurationMs.observe(
130
+ {
131
+ rng_range: rangeKey,
132
+ engine_type: this.getEngineType(),
133
+ },
134
+ duration
135
+ );
136
+ return;
137
+ }
138
+ await this.storage.addItemsToBuffer(buffer, values);
139
+ this.metrics.rngBufferFillLevel.set(
140
+ {
141
+ rng_range: rangeKey,
142
+ engine_type: this.getEngineType(),
143
+ },
144
+ buffer.items.length
145
+ );
146
+ this.metrics.rngBufferFillRatio.set(
147
+ {
148
+ rng_range: rangeKey,
149
+ engine_type: this.getEngineType(),
150
+ },
151
+ buffer.items.length / this.size
152
+ );
153
+
154
+ const duration = Date.now() - refillStartTime;
155
+ this.metrics.rngBufferRefillDurationMs.observe(
156
+ {
157
+ rng_range: rangeKey,
158
+ engine_type: this.getEngineType(),
159
+ },
160
+ duration
161
+ );
162
+ } catch (error) {
163
+ const errorMessage =
164
+ error instanceof Error ? error.message : String(error);
165
+ this.metrics.rngBufferRefillFailuresTotal.inc({
166
+ rng_range: rangeKey,
167
+ engine_type: this.getEngineType(),
168
+ reason,
169
+ error: errorMessage,
170
+ });
171
+
172
+ const duration = Date.now() - refillStartTime;
173
+ this.metrics.rngBufferRefillDurationMs.observe(
174
+ {
175
+ rng_range: rangeKey,
176
+ engine_type: this.getEngineType(),
177
+ },
178
+ duration
179
+ );
180
+
181
+ throw error;
182
+ }
183
+ }
184
+
185
+ async pullNumberByBuffer(
186
+ buffer: SingleRingBuffer
187
+ ): Promise<RingBufferValue[]> {
188
+ const count = this.size - buffer.items.length;
189
+ if (count <= 0) {
190
+ return [];
191
+ }
192
+ const values = await this.clientCore.getBatchNumbersWithSeeds({
193
+ min: buffer.range.min,
194
+ max: buffer.range.max,
195
+ count,
196
+ });
197
+ return values.result as RingBufferValue[];
198
+ }
199
+
200
+ createBuffer(min: number, max: number): SingleRingBuffer {
201
+ this.metrics.rngBufferCapacity.set(
202
+ {
203
+ rng_range: this.getRangeKey(min, max),
204
+ engine_type: this.getEngineType(),
205
+ },
206
+ this.size
207
+ );
208
+
209
+ return {
210
+ items: [],
211
+ range: { min, max },
212
+ };
213
+ }
214
+ }
@@ -0,0 +1,48 @@
1
+ import { RingBufferValue, SingleRingBuffer } from './interfaces';
2
+
3
+ export class RingStorageMemory {
4
+ private storage: { [key: string]: SingleRingBuffer };
5
+
6
+ constructor() {
7
+ this.storage = {};
8
+ }
9
+
10
+ getBufferName(min: number, max: number): string {
11
+ return `${min}-${max}`;
12
+ }
13
+
14
+ async saveBuffer(buffer: SingleRingBuffer): Promise<void> {
15
+ this.storage[this.getBufferName(buffer.range.min, buffer.range.max)] =
16
+ buffer;
17
+ }
18
+
19
+ async getBuffer(name: string): Promise<SingleRingBuffer> {
20
+ return this.storage[name];
21
+ }
22
+
23
+ async getFromBuffer(
24
+ name: string,
25
+ count = 1
26
+ ): Promise<RingBufferValue[] | undefined> {
27
+ const buffer = await this.getBuffer(name);
28
+ if (!buffer) {
29
+ return undefined;
30
+ }
31
+ if (buffer.items.length < count) {
32
+ return undefined;
33
+ }
34
+ const items = buffer.items.splice(0, count);
35
+ if (items.length === 0) {
36
+ return undefined;
37
+ }
38
+ return items;
39
+ }
40
+
41
+ async addItemsToBuffer(
42
+ buffer: SingleRingBuffer,
43
+ items: RingBufferValue[]
44
+ ): Promise<void> {
45
+ buffer.items.push(...items);
46
+ await this.saveBuffer(buffer);
47
+ }
48
+ }
@@ -0,0 +1,59 @@
1
+ import { RingBufferValue, SingleRingBuffer } from './interfaces';
2
+ import { RingStorageMemory } from './ring-storage-memory';
3
+
4
+ export enum StorageType {
5
+ IN_MEMORY = 'in_memory',
6
+ REDIS = 'redis',
7
+ }
8
+
9
+ export class RingStorage {
10
+ private storage: RingStorageMemory;
11
+ constructor(private readonly storageType: StorageType) {
12
+ this.storage = new RingStorageMemory();
13
+ }
14
+
15
+ async getFromBuffer(
16
+ buffer: SingleRingBuffer,
17
+ count = 1
18
+ ): Promise<RingBufferValue[] | undefined> {
19
+ if (this.storageType === StorageType.IN_MEMORY) {
20
+ return this.storage.getFromBuffer(
21
+ this.storage.getBufferName(buffer.range.min, buffer.range.max),
22
+ count
23
+ );
24
+ }
25
+ return undefined;
26
+ }
27
+
28
+ async saveBuffer(buffer: SingleRingBuffer): Promise<void> {
29
+ if (this.storageType === StorageType.IN_MEMORY) {
30
+ this.storage.saveBuffer(buffer);
31
+ }
32
+ }
33
+
34
+ async getBufferByRange(
35
+ min: number,
36
+ max: number
37
+ ): Promise<SingleRingBuffer | undefined> {
38
+ if (this.storageType === StorageType.IN_MEMORY) {
39
+ return this.storage.getBuffer(this.storage.getBufferName(min, max));
40
+ }
41
+ return undefined;
42
+ }
43
+
44
+ async getBuffer(name: string): Promise<SingleRingBuffer | undefined> {
45
+ if (this.storageType === StorageType.IN_MEMORY) {
46
+ return this.storage.getBuffer(name);
47
+ }
48
+ return undefined;
49
+ }
50
+
51
+ async addItemsToBuffer(
52
+ buffer: SingleRingBuffer,
53
+ items: RingBufferValue[]
54
+ ): Promise<void> {
55
+ if (this.storageType === StorageType.IN_MEMORY) {
56
+ this.storage.addItemsToBuffer(buffer, items);
57
+ }
58
+ }
59
+ }
@@ -0,0 +1,190 @@
1
+ import { RngClientCore } from './core/rng-client-core';
2
+ import { RngClientConfig } from './interfaces/client-interfaces';
3
+ import { StorageType } from './ring-buffer/ring-storage';
4
+ import {
5
+ RngSingleResponse,
6
+ RngBatchResponse,
7
+ RngSingleRequest,
8
+ RngBatchRequest,
9
+ RngSingleFloatRequest,
10
+ RngBatchFloatRequest,
11
+ } from './http/http-client.types';
12
+ import { RingBuffer } from './ring-buffer/ring-buffer';
13
+ import { defaultMetricsHandlers } from './metrics/default-metrics-handlers';
14
+
15
+ /**
16
+ * RNG Client - High-level API for client-side random number generation
17
+ *
18
+ * This is the main entry point for client-side RNG operations.
19
+ * It provides a simple interface for generating random numbers
20
+ * via HTTP communication with the RNG service.
21
+ */
22
+ export class RngClient {
23
+ private readonly clientCore: RngClientCore;
24
+ private readonly ringBuffer: RingBuffer;
25
+
26
+ constructor(config: RngClientConfig) {
27
+ this.clientCore = new RngClientCore(config);
28
+ this.ringBuffer = new RingBuffer({
29
+ size: config.poolingSize || 2000,
30
+ clientCore: this.clientCore,
31
+ storageType: config.storageType || StorageType.IN_MEMORY,
32
+ metrics: {
33
+ ...defaultMetricsHandlers,
34
+ ...config.metrics?.handlers,
35
+ },
36
+ });
37
+ }
38
+
39
+ /**
40
+ * Get a single random number
41
+ * @param min Minimum value (inclusive)
42
+ * @param max Maximum value (inclusive)
43
+ * @param seed Optional seed for deterministic generation
44
+ * @returns Random integer result
45
+ */
46
+ async getSingleNumber(
47
+ min: number,
48
+ max: number,
49
+ seed?: number
50
+ ): Promise<{ value: number; seed: number }> {
51
+ const data: RngSingleRequest = {
52
+ min,
53
+ max,
54
+ };
55
+ if (seed) {
56
+ data.seed = seed;
57
+ } else {
58
+ const item = await this.ringBuffer.getNumbersByRange(min, max, 1);
59
+ if (item && item.length > 0) {
60
+ return { value: item[0].value, seed: item[0].seed };
61
+ }
62
+ }
63
+ const response = await this.clientCore.getSingleNumber(data);
64
+ return { value: response.result, seed: response.seed };
65
+ }
66
+
67
+ /**
68
+ * Get a batch of random numbers
69
+ * @param min Minimum value (inclusive)
70
+ * @param max Maximum value (inclusive)
71
+ * @param count Number of values to generate
72
+ * @param seed Optional seed for deterministic generation
73
+ * @returns Batch of random integers
74
+ */
75
+ async getBatchNumbers(
76
+ min: number,
77
+ max: number,
78
+ count: number,
79
+ seed?: number
80
+ ): Promise<number[]> {
81
+ const data: RngBatchRequest = {
82
+ min,
83
+ max,
84
+ count,
85
+ };
86
+ if (seed) {
87
+ data.seed = seed;
88
+ }
89
+ const response = await this.clientCore.getBatchNumbers(data);
90
+
91
+ return response.result;
92
+ }
93
+
94
+ /**
95
+ * Get a batch of random numbers with seeds
96
+ * @param min Minimum value (inclusive)
97
+ * @param max Maximum value (inclusive)
98
+ * @param count Number of values to generate
99
+ * @param seed Optional seed for deterministic generation
100
+ * @returns Batch of random integers
101
+ */
102
+ async getBatchNumbersWithSeeds(
103
+ min: number,
104
+ max: number,
105
+ count: number,
106
+ seed?: number
107
+ ): Promise<{ value: number; seed: number }[]> {
108
+ const data: RngBatchRequest = {
109
+ min,
110
+ max,
111
+ count,
112
+ };
113
+ if (seed) {
114
+ data.seed = seed;
115
+ } else {
116
+ const item = await this.ringBuffer.getNumbersByRange(min, max, count);
117
+ if (item && item.length > 0) {
118
+ return item;
119
+ }
120
+ }
121
+ const response = await this.clientCore.getBatchNumbersWithSeeds(data);
122
+
123
+ return response.result.map((item) => ({
124
+ value: item.value,
125
+ seed: item.seed,
126
+ }));
127
+ }
128
+
129
+ /**
130
+ * Get a single random float
131
+ * @param seed Optional seed for deterministic generation
132
+ * @returns Random float result
133
+ */
134
+ async getSingleFloat(seed?: number): Promise<RngSingleResponse> {
135
+ const data: RngSingleFloatRequest = {};
136
+ if (seed) {
137
+ data.seed = seed;
138
+ }
139
+ return this.clientCore.getSingleFloat(data);
140
+ }
141
+
142
+ /**
143
+ * Get a batch of random floats
144
+ * @param count Number of values to generate
145
+ * @param seed Optional seed for deterministic generation
146
+ * @returns Batch of random floats
147
+ */
148
+ async getBatchFloats(
149
+ count: number,
150
+ seed?: number
151
+ ): Promise<RngBatchResponse> {
152
+ const data: RngBatchFloatRequest = { count };
153
+ if (seed) {
154
+ data.seed = seed;
155
+ }
156
+ return this.clientCore.getBatchFloats(data);
157
+ }
158
+
159
+ /**
160
+ * Get a random number
161
+ * @param min Minimum value (inclusive)
162
+ * @param max Maximum value (inclusive)
163
+ * @param seed Optional seed for deterministic generation
164
+ * @returns Random integer result
165
+ */
166
+ async getRandomNumber(
167
+ min: number,
168
+ max: number,
169
+ seed?: number
170
+ ): Promise<RngSingleResponse> {
171
+ const data: RngSingleRequest = { min, max };
172
+ if (seed) {
173
+ data.seed = seed;
174
+ }
175
+ return this.clientCore.getRandomNumber(data);
176
+ }
177
+
178
+ /**
179
+ * Get a random float
180
+ * @param seed Optional seed for deterministic generation
181
+ * @returns Random float result
182
+ */
183
+ async getRandomFloat(seed?: number): Promise<RngSingleResponse> {
184
+ const data: RngSingleFloatRequest = {};
185
+ if (seed) {
186
+ data.seed = seed;
187
+ }
188
+ return this.clientCore.getRandomFloat(data);
189
+ }
190
+ }
package/src/rng.proto ADDED
@@ -0,0 +1,102 @@
1
+ syntax = "proto3";
2
+
3
+ package rng;
4
+
5
+ service RngService {
6
+ rpc Single (SingleRequest) returns (SingleResponse);
7
+ rpc SingleBatch (BatchRequest) returns (BatchResponse);
8
+ rpc SingleBatchWithSeeds (BatchRequest) returns (BatchWithSeedsResponse);
9
+ rpc Float (FloatRequest) returns (FloatResponse);
10
+ rpc FloatBatch (BatchFloatRequest) returns (BatchFloatResponse);
11
+ rpc FloatBatchWithSeeds (BatchFloatRequest) returns (BatchFloatWithSeedsResponse);
12
+ }
13
+
14
+ message SingleRequest {
15
+ int32 min = 1;
16
+ int32 max = 2;
17
+ optional string sessionId = 3;
18
+ optional int32 seed = 4;
19
+ }
20
+
21
+ message SingleResponse {
22
+ string id = 1;
23
+ int32 seed = 2;
24
+ int32 result = 3;
25
+ int32 min = 4;
26
+ int32 max = 5;
27
+ string createdAt = 6;
28
+ optional string sessionId = 7;
29
+ }
30
+
31
+ message FloatRequest {
32
+ optional string sessionId = 1;
33
+ optional int32 seed = 2;
34
+ }
35
+
36
+ message FloatResponse {
37
+ string id = 1;
38
+ int32 seed = 2;
39
+ double result = 3;
40
+ string createdAt = 4;
41
+ optional string sessionId = 5;
42
+ }
43
+
44
+ message BatchFloatRequest {
45
+ int32 count = 1;
46
+ optional string sessionId = 2;
47
+ optional int32 seed = 3;
48
+ }
49
+
50
+ message BatchFloatResponse {
51
+ string id = 1;
52
+ int32 seed = 2;
53
+ repeated double result = 3;
54
+ string createdAt = 4;
55
+ optional string sessionId = 5;
56
+ }
57
+
58
+ message BatchFloatWithSeedsResponse {
59
+ string id = 1;
60
+ int32 seed = 2;
61
+ repeated BatchFloatItem result = 3;
62
+ string createdAt = 4;
63
+ optional string sessionId = 5;
64
+ }
65
+
66
+ message BatchFloatItem {
67
+ double value = 1;
68
+ int32 seed = 2;
69
+ }
70
+
71
+ message BatchRequest {
72
+ int32 min = 1;
73
+ int32 max = 2;
74
+ int32 count = 3;
75
+ optional string sessionId = 4;
76
+ optional int32 seed = 5;
77
+ }
78
+
79
+ message BatchResponse {
80
+ string id = 1;
81
+ int32 seed = 2;
82
+ repeated int32 result = 3;
83
+ int32 min = 4;
84
+ int32 max = 5;
85
+ string createdAt = 6;
86
+ optional string sessionId = 7;
87
+ }
88
+
89
+ message BatchWithSeedsResponse {
90
+ string id = 1;
91
+ int32 seed = 2;
92
+ repeated BatchItem result = 3;
93
+ int32 min = 4;
94
+ int32 max = 5;
95
+ string createdAt = 6;
96
+ optional string sessionId = 7;
97
+ }
98
+
99
+ message BatchItem {
100
+ int32 value = 1;
101
+ uint64 seed = 2;
102
+ }
@@ -1 +0,0 @@
1
- {"version":3,"file":"rng-client-core.d.ts","sourceRoot":"","sources":["../../src/core/rng-client-core.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,iCAAiC,CAAC;AAIlE,OAAO,EACL,oBAAoB,EACpB,eAAe,EACf,gBAAgB,EAChB,yBAAyB,EACzB,qBAAqB,EACrB,gBAAgB,EAChB,iBAAiB,EAClB,MAAM,2BAA2B,CAAC;AAEnC,qBAAa,aAAa;IACxB,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAkB;IACzC,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAqB;gBAEnC,MAAM,EAAE,eAAe;IAUtB,eAAe,CAC1B,OAAO,EAAE,gBAAgB,GACxB,OAAO,CAAC,iBAAiB,CAAC;IAIhB,eAAe,CAC1B,OAAO,EAAE,gBAAgB,GACxB,OAAO,CAAC,iBAAiB,CAAC;IAIhB,cAAc,CACzB,OAAO,EAAE,qBAAqB,GAC7B,OAAO,CAAC,iBAAiB,CAAC;IAMhB,cAAc,CACzB,OAAO,EAAE,qBAAqB,GAC7B,OAAO,CAAC,iBAAiB,CAAC;IAMhB,cAAc,CACzB,OAAO,EAAE,oBAAoB,GAC5B,OAAO,CAAC,gBAAgB,CAAC;IAIf,eAAe,CAC1B,IAAI,EAAE,eAAe,GACpB,OAAO,CAAC,gBAAgB,CAAC;IAIf,wBAAwB,CACnC,OAAO,EAAE,eAAe,GACvB,OAAO,CAAC,yBAAyB,CAAC;IAIxB,sBAAsB,CACjC,OAAO,EAAE,qBAAqB,GAC7B,OAAO,CAAC,yBAAyB,CAAC;CAGtC"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"rng-client-core.js","sourceRoot":"","sources":["../../src/core/rng-client-core.ts"],"names":[],"mappings":";;;AAEA,6DAAwD;AACxD,6DAAwD;AAWxD,MAAa,aAAa;IAIxB,YAAY,MAAuB;QACjC,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC;QAErB,IAAI,MAAM,CAAC,YAAY,KAAK,MAAM,EAAE,CAAC;YACnC,IAAI,CAAC,SAAS,GAAG,IAAI,+BAAa,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;QACrD,CAAC;aAAM,CAAC;YACN,IAAI,CAAC,SAAS,GAAG,IAAI,+BAAa,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC;QACvD,CAAC;IACH,CAAC;IAEM,KAAK,CAAC,eAAe,CAC1B,OAAyB;QAEzB,OAAO,IAAI,CAAC,SAAS,CAAC,eAAe,CAAC,OAAO,CAAC,CAAC;IACjD,CAAC;IAEM,KAAK,CAAC,eAAe,CAC1B,OAAyB;QAEzB,OAAO,IAAI,CAAC,SAAS,CAAC,eAAe,CAAC,OAAO,CAAC,CAAC;IACjD,CAAC;IAEM,KAAK,CAAC,cAAc,CACzB,OAA8B;QAE9B,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,SAAS,CAAC,cAAc,CAAC,OAAO,CAAC,CAAC;QAE9D,OAAO,QAAQ,CAAC;IAClB,CAAC;IAEM,KAAK,CAAC,cAAc,CACzB,OAA8B;QAE9B,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,SAAS,CAAC,cAAc,CAAC,OAAO,CAAC,CAAC;QAE9D,OAAO,QAAQ,CAAC;IAClB,CAAC;IAEM,KAAK,CAAC,cAAc,CACzB,OAA6B;QAE7B,OAAO,IAAI,CAAC,SAAS,CAAC,cAAc,CAAC,OAAO,CAAC,CAAC;IAChD,CAAC;IAEM,KAAK,CAAC,eAAe,CAC1B,IAAqB;QAErB,OAAO,IAAI,CAAC,SAAS,CAAC,eAAe,CAAC,IAAI,CAAC,CAAC;IAC9C,CAAC;IAEM,KAAK,CAAC,wBAAwB,CACnC,OAAwB;QAExB,OAAO,IAAI,CAAC,SAAS,CAAC,wBAAwB,CAAC,OAAO,CAAC,CAAC;IAC1D,CAAC;IAEM,KAAK,CAAC,sBAAsB,CACjC,OAA8B;QAE9B,OAAO,IAAI,CAAC,SAAS,CAAC,sBAAsB,CAAC,OAAO,CAAC,CAAC;IACxD,CAAC;CACF;AAjED,sCAiEC"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"rng-errors.d.ts","sourceRoot":"","sources":["../../src/errors/rng-errors.ts"],"names":[],"mappings":"AAEA,qBAAa,eAAgB,SAAQ,KAAK;aAGtB,IAAI,EAAE,MAAM;aACZ,aAAa,CAAC,EAAE,OAAO;gBAFvC,OAAO,EAAE,MAAM,EACC,IAAI,EAAE,MAAM,EACZ,aAAa,CAAC,EAAE,OAAO,YAAA;CAK1C;AAED,qBAAa,kBAAmB,SAAQ,eAAe;gBAEnD,OAAO,GAAE,MAA2C,EACpD,aAAa,CAAC,EAAE,OAAO;CAK1B;AAED,qBAAa,mBAAoB,SAAQ,KAAK;aAG1B,aAAa,CAAC,EAAE,OAAO;gBADvC,OAAO,GAAE,MAA2C,EACpC,aAAa,CAAC,EAAE,OAAO,YAAA;CAK1C;AAED,qBAAa,gBAAiB,SAAQ,KAAK;aAGvB,UAAU,EAAE,MAAM;aAClB,aAAa,CAAC,EAAE,OAAO;gBAFvC,OAAO,EAAE,MAAM,EACC,UAAU,EAAE,MAAM,EAClB,aAAa,CAAC,EAAE,OAAO,YAAA;CAK1C;AAED,wBAAgB,eAAe,CAC7B,GAAG,EAAE,OAAO,EACZ,SAAS,EAAE,MAAM,EACjB,OAAO,CAAC,EAAE,MAAM,GACf,KAAK,CA+CP"}