@sequenceholdings/managed-functions 0.1.1

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/dist/limits.js ADDED
@@ -0,0 +1,98 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.MF_LIMITS_DEFAULTS = exports.MF_LIMITS_CAPS = exports.managedFunctionWorkloadLimitsSchema = exports.MANAGED_FUNCTION_LIMITS = void 0;
4
+ const zod_1 = require("zod");
5
+ exports.MANAGED_FUNCTION_LIMITS = {
6
+ environment: {
7
+ functions: { max: 100, scope: 'Non-archived functions across all organizations; undeployed shells count' },
8
+ },
9
+ workload: {
10
+ memory_mb: { min: 128, max: 2048, default: 256, unit: 'MiB per instance' },
11
+ timeout_seconds: { min: 1, max: 540, default: 60, unit: 'seconds' },
12
+ min_instances: { min: 0, max: 10, default: 1, scope: 'Cannot exceed max_instances; warm instances incur idle charges' },
13
+ max_instances: { min: 2, max: 10, default: 3, scope: 'Autoscaling ceiling; must allow at least two instances, and GCP may temporarily exceed it' },
14
+ invoke_rate_per_minute: { min: 1, max: 600, default: 60, window_seconds: 60, scope: 'Per function across all Atlas replicas in the environment; Redis-backed fixed window. Redis unavailability rejects invocations (503); key loss resets the window' },
15
+ max_request_bytes: { max: 1024 * 1024, unit: 'bytes', configurable: false },
16
+ max_response_bytes: { max: 4 * 1024 * 1024, unit: 'bytes', configurable: false },
17
+ cpu: {
18
+ configurable: true, default: 'auto', min: 1, max: 2,
19
+ min_memory_mb_for_multiple_cpus: 512,
20
+ scope: 'auto uses provider memory-derived allocation; explicit CPU must be a whole vCPU. Multiple CPUs require the minimum memory listed here',
21
+ },
22
+ concurrency: {
23
+ configurable: true, min: 1, max: 80, default: 1,
24
+ scope: 'Simultaneous requests per instance; values above 1 require explicit cpu (not auto). Requests share instance CPU and memory',
25
+ },
26
+ },
27
+ cache: {
28
+ enabled: { default: false },
29
+ tier: { allowed: ['custom-pico', 'custom-micro', 'custom-mini'], default: 'custom-pico' },
30
+ replicas: { min: 0, max: 5, default: 0 },
31
+ default_ttl_seconds: { min: 1, max: 86400, default: 30, unit: 'seconds' },
32
+ max_key_bytes: { max: 512, unit: 'bytes' },
33
+ max_value_bytes: { max: 1024 * 1024, unit: 'bytes' },
34
+ },
35
+ bundle: {
36
+ files: { max: 2000 },
37
+ file_bytes: { max: 5 * 1024 * 1024, unit: 'bytes' },
38
+ source_bytes: { max: 25 * 1024 * 1024, unit: 'bytes unpacked' },
39
+ request_bytes: { max: 32 * 1024 * 1024, unit: 'bytes in deploy request' },
40
+ },
41
+ };
42
+ function integerLimit(limit) {
43
+ return zod_1.z.number().int().min(limit.min).max(limit.max).default(limit.default);
44
+ }
45
+ const workload = exports.MANAGED_FUNCTION_LIMITS.workload;
46
+ exports.managedFunctionWorkloadLimitsSchema = zod_1.z.object({
47
+ memory_mb: integerLimit(workload.memory_mb),
48
+ cpu: zod_1.z.union([
49
+ zod_1.z.literal(workload.cpu.default),
50
+ zod_1.z.number().int().min(workload.cpu.min).max(workload.cpu.max),
51
+ ]).default(workload.cpu.default),
52
+ concurrency: integerLimit(workload.concurrency),
53
+ timeout_seconds: integerLimit(workload.timeout_seconds),
54
+ min_instances: integerLimit(workload.min_instances),
55
+ max_instances: integerLimit(workload.max_instances),
56
+ invoke_rate_per_minute: integerLimit(workload.invoke_rate_per_minute),
57
+ }).superRefine((limits, ctx) => {
58
+ if (limits.cpu === 'auto' && limits.concurrency > 1) {
59
+ ctx.addIssue({
60
+ code: 'custom', path: ['concurrency'],
61
+ message: 'concurrency above 1 requires an explicit cpu allocation; auto may allocate a fractional CPU',
62
+ });
63
+ }
64
+ if (typeof limits.cpu === 'number' && limits.cpu > 1 && limits.memory_mb < workload.cpu.min_memory_mb_for_multiple_cpus) {
65
+ ctx.addIssue({
66
+ code: 'custom', path: ['memory_mb'],
67
+ message: `Multiple CPUs require at least ${workload.cpu.min_memory_mb_for_multiple_cpus} MiB of memory`,
68
+ });
69
+ }
70
+ if (limits.min_instances > limits.max_instances) {
71
+ ctx.addIssue({
72
+ code: 'custom',
73
+ message: 'min_instances cannot exceed max_instances',
74
+ path: ['min_instances'],
75
+ });
76
+ }
77
+ }).prefault({});
78
+ exports.MF_LIMITS_CAPS = {
79
+ cpu: workload.cpu.max,
80
+ concurrency: workload.concurrency.max,
81
+ memoryMb: workload.memory_mb.max,
82
+ timeoutSeconds: workload.timeout_seconds.max,
83
+ maxInstances: workload.max_instances.max,
84
+ invokeRatePerMinute: workload.invoke_rate_per_minute.max,
85
+ maxRequestBytes: workload.max_request_bytes.max,
86
+ maxResponseBytes: workload.max_response_bytes.max,
87
+ };
88
+ exports.MF_LIMITS_DEFAULTS = {
89
+ cpu: workload.cpu.default,
90
+ concurrency: workload.concurrency.default,
91
+ memoryMb: workload.memory_mb.default,
92
+ timeoutSeconds: workload.timeout_seconds.default,
93
+ minInstances: workload.min_instances.default,
94
+ maxInstances: workload.max_instances.default,
95
+ invokeRatePerMinute: workload.invoke_rate_per_minute.default,
96
+ maxRequestBytes: workload.max_request_bytes.max,
97
+ maxResponseBytes: workload.max_response_bytes.max,
98
+ };
@@ -0,0 +1,22 @@
1
+ import { type CacheStore } from './cache';
2
+ export declare class MemoryStore implements CacheStore {
3
+ private readonly entries;
4
+ private used;
5
+ private readonly maxBytes;
6
+ private readonly now;
7
+ private readonly maxEntries;
8
+ constructor({ maxBytes, now, }?: {
9
+ maxBytes?: number;
10
+ now?: () => number;
11
+ });
12
+ get bytes(): number;
13
+ get(key: string): Promise<string | null>;
14
+ set({ key, value, ttlSeconds, onlyIfAbsent, }: {
15
+ key: string;
16
+ value: string;
17
+ ttlSeconds: number;
18
+ onlyIfAbsent: boolean;
19
+ }): Promise<boolean>;
20
+ delete(key: string): Promise<boolean>;
21
+ private remove;
22
+ }
package/dist/memory.js ADDED
@@ -0,0 +1,67 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.MemoryStore = void 0;
4
+ const cache_1 = require("./cache");
5
+ class MemoryStore {
6
+ entries = new Map();
7
+ used = 0;
8
+ maxBytes;
9
+ now;
10
+ maxEntries = 10000;
11
+ constructor({ maxBytes = 16 * 1024 * 1024, now = Date.now, } = {}) {
12
+ this.maxBytes = maxBytes;
13
+ this.now = now;
14
+ }
15
+ get bytes() {
16
+ return this.used;
17
+ }
18
+ async get(key) {
19
+ const entry = this.entries.get(key);
20
+ if (!entry)
21
+ return null;
22
+ if (entry.expiresAt <= this.now()) {
23
+ this.remove(key);
24
+ return null;
25
+ }
26
+ this.entries.delete(key);
27
+ this.entries.set(key, entry);
28
+ return entry.value;
29
+ }
30
+ async set({ key, value, ttlSeconds, onlyIfAbsent, }) {
31
+ const existing = this.entries.get(key);
32
+ if (onlyIfAbsent && existing && existing.expiresAt > this.now())
33
+ return false;
34
+ const bytes = Buffer.byteLength(key) + Buffer.byteLength(value);
35
+ if (bytes > this.maxBytes)
36
+ throw new cache_1.CacheError('INVALID_VALUE');
37
+ this.remove(key);
38
+ while (this.used + bytes > this.maxBytes ||
39
+ this.entries.size >= this.maxEntries) {
40
+ const first = this.entries.keys().next().value;
41
+ if (first === undefined)
42
+ break;
43
+ this.remove(first);
44
+ }
45
+ this.entries.set(key, {
46
+ value,
47
+ expiresAt: this.now() + ttlSeconds * 1000,
48
+ bytes,
49
+ });
50
+ this.used += bytes;
51
+ return true;
52
+ }
53
+ async delete(key) {
54
+ const entry = this.entries.get(key);
55
+ const exists = !!entry && entry.expiresAt > this.now();
56
+ this.remove(key);
57
+ return exists;
58
+ }
59
+ remove(key) {
60
+ const entry = this.entries.get(key);
61
+ if (entry) {
62
+ this.used -= entry.bytes;
63
+ this.entries.delete(key);
64
+ }
65
+ }
66
+ }
67
+ exports.MemoryStore = MemoryStore;