@undefineds.co/xpod 0.1.7 → 0.2.0-preview.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.
- package/README.md +141 -2
- package/config/cli.json +9 -71
- package/config/cloud.json +34 -7
- package/config/local.json +6 -2
- package/config/resolver.json +11 -49
- package/config/runtime-open.json +22 -0
- package/config/xpod.base.json +32 -0
- package/config/xpod.cluster.json +2 -44
- package/config/xpod.json +5 -2
- package/dist/api/auth/AuthContext.d.ts +12 -1
- package/dist/api/auth/AuthContext.js +18 -1
- package/dist/api/auth/AuthContext.js.map +1 -1
- package/dist/api/auth/ClientCredentialsAuthenticator.d.ts +0 -1
- package/dist/api/auth/ClientCredentialsAuthenticator.js.map +1 -1
- package/dist/api/auth/ServiceTokenAuthenticator.d.ts +18 -0
- package/dist/api/auth/ServiceTokenAuthenticator.js +50 -0
- package/dist/api/auth/ServiceTokenAuthenticator.js.map +1 -0
- package/dist/api/auth/index.d.ts +1 -0
- package/dist/api/auth/index.js +1 -0
- package/dist/api/auth/index.js.map +1 -1
- package/dist/api/chatkit/ai-provider.d.ts +0 -10
- package/dist/api/chatkit/ai-provider.js +11 -120
- package/dist/api/chatkit/ai-provider.js.map +1 -1
- package/dist/api/chatkit/default-agent.js +11 -8
- package/dist/api/chatkit/default-agent.js.map +1 -1
- package/dist/api/chatkit/pod-store.js +19 -3
- package/dist/api/chatkit/pod-store.js.map +1 -1
- package/dist/api/chatkit/schema.d.ts +9 -3
- package/dist/api/chatkit/schema.js +14 -6
- package/dist/api/chatkit/schema.js.map +1 -1
- package/dist/api/container/business-token.d.ts +9 -0
- package/dist/api/container/business-token.js +32 -0
- package/dist/api/container/business-token.js.map +1 -0
- package/dist/api/container/cloud.js +36 -12
- package/dist/api/container/cloud.js.map +1 -1
- package/dist/api/container/common.js +12 -5
- package/dist/api/container/common.js.map +1 -1
- package/dist/api/container/index.js +94 -14
- package/dist/api/container/index.js.map +1 -1
- package/dist/api/container/local.js +2 -1
- package/dist/api/container/local.js.map +1 -1
- package/dist/api/container/routes.js +81 -9
- package/dist/api/container/routes.js.map +1 -1
- package/dist/api/container/types.d.ts +8 -6
- package/dist/api/container/types.js.map +1 -1
- package/dist/api/handlers/AdminHandler.js +9 -9
- package/dist/api/handlers/AdminHandler.js.map +1 -1
- package/dist/api/handlers/ApiKeyHandler.js +0 -6
- package/dist/api/handlers/ApiKeyHandler.js.map +1 -1
- package/dist/api/handlers/EdgeNodeSignalHandler.d.ts +17 -0
- package/dist/api/handlers/EdgeNodeSignalHandler.js +171 -0
- package/dist/api/handlers/EdgeNodeSignalHandler.js.map +1 -0
- package/dist/api/handlers/PodManagementHandler.d.ts +5 -4
- package/dist/api/handlers/PodManagementHandler.js +11 -10
- package/dist/api/handlers/PodManagementHandler.js.map +1 -1
- package/dist/api/handlers/ProvisionHandler.d.ts +42 -0
- package/dist/api/handlers/ProvisionHandler.js +161 -0
- package/dist/api/handlers/ProvisionHandler.js.map +1 -0
- package/dist/api/handlers/QuotaHandler.d.ts +7 -7
- package/dist/api/handlers/QuotaHandler.js +143 -73
- package/dist/api/handlers/QuotaHandler.js.map +1 -1
- package/dist/api/handlers/SubdomainClientHandler.js +2 -2
- package/dist/api/handlers/SubdomainClientHandler.js.map +1 -1
- package/dist/api/handlers/SubdomainHandler.js +13 -8
- package/dist/api/handlers/SubdomainHandler.js.map +1 -1
- package/dist/api/handlers/UsageHandler.d.ts +14 -0
- package/dist/api/handlers/UsageHandler.js +123 -0
- package/dist/api/handlers/UsageHandler.js.map +1 -0
- package/dist/api/handlers/index.d.ts +3 -1
- package/dist/api/handlers/index.js +3 -1
- package/dist/api/handlers/index.js.map +1 -1
- package/dist/api/main.js +18 -0
- package/dist/api/main.js.map +1 -1
- package/dist/api/middleware/OpenAuthMiddleware.d.ts +12 -0
- package/dist/api/middleware/OpenAuthMiddleware.js +27 -0
- package/dist/api/middleware/OpenAuthMiddleware.js.map +1 -0
- package/dist/api/runtime.d.ts +15 -0
- package/dist/api/runtime.js +104 -0
- package/dist/api/runtime.js.map +1 -0
- package/dist/api/service/VercelChatService.d.ts +16 -7
- package/dist/api/service/VercelChatService.js +98 -178
- package/dist/api/service/VercelChatService.js.map +1 -1
- package/dist/api/store/DrizzleClientCredentialsStore.d.ts +6 -11
- package/dist/api/store/DrizzleClientCredentialsStore.js +9 -39
- package/dist/api/store/DrizzleClientCredentialsStore.js.map +1 -1
- package/dist/authorization/AuthModeSelector.d.ts +10 -0
- package/dist/authorization/AuthModeSelector.js +27 -0
- package/dist/authorization/AuthModeSelector.js.map +1 -0
- package/dist/authorization/AuthModeSelector.jsonld +81 -0
- package/dist/cli/commands/account.d.ts +6 -0
- package/dist/cli/commands/account.js +119 -0
- package/dist/cli/commands/account.js.map +1 -0
- package/dist/cli/commands/auth.js +20 -29
- package/dist/cli/commands/auth.js.map +1 -1
- package/dist/cli/commands/backup.d.ts +15 -0
- package/dist/cli/commands/backup.js +286 -0
- package/dist/cli/commands/backup.js.map +1 -0
- package/dist/cli/commands/config.d.ts +34 -3
- package/dist/cli/commands/config.js +195 -258
- package/dist/cli/commands/config.js.map +1 -1
- package/dist/cli/commands/doctor.d.ts +6 -0
- package/dist/cli/commands/doctor.js +94 -0
- package/dist/cli/commands/doctor.js.map +1 -0
- package/dist/cli/commands/pod.d.ts +6 -0
- package/dist/cli/commands/pod.js +124 -0
- package/dist/cli/commands/pod.js.map +1 -0
- package/dist/cli/commands/start.js +28 -5
- package/dist/cli/commands/start.js.map +1 -1
- package/dist/cli/index.js +9 -0
- package/dist/cli/index.js.map +1 -1
- package/dist/cli/lib/credentials-store.d.ts +17 -0
- package/dist/cli/lib/credentials-store.js +73 -0
- package/dist/cli/lib/credentials-store.js.map +1 -0
- package/dist/cli/lib/css-account.d.ts +17 -0
- package/dist/cli/lib/css-account.js +56 -0
- package/dist/cli/lib/css-account.js.map +1 -1
- package/dist/cli/lib/pod-thread-store.d.ts +57 -0
- package/dist/cli/lib/pod-thread-store.js +310 -0
- package/dist/cli/lib/pod-thread-store.js.map +1 -0
- package/dist/cli/lib/solid-auth.d.ts +20 -0
- package/dist/cli/lib/solid-auth.js +70 -0
- package/dist/cli/lib/solid-auth.js.map +1 -0
- package/dist/components/components.jsonld +5 -8
- package/dist/components/context.jsonld +114 -244
- package/dist/edge/EdgeNodeAgent.js +2 -2
- package/dist/edge/EdgeNodeAgent.js.map +1 -1
- package/dist/edge/EdgeNodeDnsCoordinator.d.ts +1 -7
- package/dist/edge/EdgeNodeDnsCoordinator.js +31 -41
- package/dist/edge/EdgeNodeDnsCoordinator.js.map +1 -1
- package/dist/edge/EdgeNodeDnsCoordinator.jsonld +1 -27
- package/dist/edge/EdgeNodeModeDetector.d.ts +1 -1
- package/dist/edge/EdgeNodeModeDetector.js +9 -11
- package/dist/edge/EdgeNodeModeDetector.js.map +1 -1
- package/dist/http/ClusterIngressRouter.js +3 -3
- package/dist/http/ClusterIngressRouter.js.map +1 -1
- package/dist/http/ClusterWebSocketConfigurator.js +2 -2
- package/dist/http/ClusterWebSocketConfigurator.js.map +1 -1
- package/dist/http/PodRoutingHttpHandler.js +2 -2
- package/dist/http/PodRoutingHttpHandler.js.map +1 -1
- package/dist/http/cluster/PodMigrationHttpHandler.d.ts +1 -1
- package/dist/http/cluster/PodMigrationHttpHandler.js +1 -1
- package/dist/http/cluster/PodMigrationHttpHandler.js.map +1 -1
- package/dist/identity/drizzle/EdgeNodeRepository.d.ts +37 -4
- package/dist/identity/drizzle/EdgeNodeRepository.js +120 -128
- package/dist/identity/drizzle/EdgeNodeRepository.js.map +1 -1
- package/dist/identity/drizzle/ServiceTokenRepository.d.ts +52 -0
- package/dist/identity/drizzle/ServiceTokenRepository.js +143 -0
- package/dist/identity/drizzle/ServiceTokenRepository.js.map +1 -0
- package/dist/identity/drizzle/db.d.ts +9 -0
- package/dist/identity/drizzle/db.js +208 -1
- package/dist/identity/drizzle/db.js.map +1 -1
- package/dist/identity/drizzle/schema.pg.d.ts +5 -0
- package/dist/identity/drizzle/schema.pg.js +49 -20
- package/dist/identity/drizzle/schema.pg.js.map +1 -1
- package/dist/identity/drizzle/schema.sqlite.d.ts +332 -57
- package/dist/identity/drizzle/schema.sqlite.js +48 -18
- package/dist/identity/drizzle/schema.sqlite.js.map +1 -1
- package/dist/identity/oidc/AutoDetectIdentityProviderHandler.js +6 -4
- package/dist/identity/oidc/AutoDetectIdentityProviderHandler.js.map +1 -1
- package/dist/index.d.ts +6 -9
- package/dist/index.js +12 -14
- package/dist/index.js.map +1 -1
- package/dist/main.js +25 -8
- package/dist/main.js.map +1 -1
- package/dist/provision/ProvisionCodeCodec.d.ts +39 -0
- package/dist/provision/ProvisionCodeCodec.js +65 -0
- package/dist/provision/ProvisionCodeCodec.js.map +1 -0
- package/dist/provision/ProvisionCodeCodec.jsonld +47 -0
- package/dist/provision/ProvisionPodCreator.d.ts +20 -0
- package/dist/provision/ProvisionPodCreator.js +84 -0
- package/dist/provision/ProvisionPodCreator.js.map +1 -0
- package/dist/provision/ProvisionPodCreator.jsonld +118 -0
- package/dist/quota/DrizzleQuotaService.d.ts +17 -3
- package/dist/quota/DrizzleQuotaService.js +108 -8
- package/dist/quota/DrizzleQuotaService.js.map +1 -1
- package/dist/quota/DrizzleQuotaService.jsonld +33 -22
- package/dist/quota/NoopQuotaService.d.ts +7 -1
- package/dist/quota/NoopQuotaService.js +12 -0
- package/dist/quota/NoopQuotaService.js.map +1 -1
- package/dist/quota/NoopQuotaService.jsonld +24 -0
- package/dist/quota/QuotaService.d.ts +17 -0
- package/dist/quota/QuotaService.js +5 -0
- package/dist/quota/QuotaService.js.map +1 -1
- package/dist/quota/QuotaService.jsonld +50 -0
- package/dist/runtime/Proxy.d.ts +22 -4
- package/dist/runtime/Proxy.js +154 -35
- package/dist/runtime/Proxy.js.map +1 -1
- package/dist/runtime/XpodRuntime.d.ts +49 -0
- package/dist/runtime/XpodRuntime.js +374 -0
- package/dist/runtime/XpodRuntime.js.map +1 -0
- package/dist/runtime/env-utils.d.ts +2 -0
- package/dist/runtime/env-utils.js +55 -0
- package/dist/runtime/env-utils.js.map +1 -0
- package/dist/runtime/index.d.ts +4 -0
- package/dist/runtime/index.js +8 -1
- package/dist/runtime/index.js.map +1 -1
- package/dist/runtime/socket-fetch.d.ts +1 -0
- package/dist/runtime/socket-fetch.js +72 -0
- package/dist/runtime/socket-fetch.js.map +1 -0
- package/dist/runtime/socket-http.d.ts +1 -0
- package/dist/runtime/socket-http.js +142 -0
- package/dist/runtime/socket-http.js.map +1 -0
- package/dist/runtime/socket-utils.d.ts +2 -0
- package/dist/runtime/socket-utils.js +34 -0
- package/dist/runtime/socket-utils.js.map +1 -0
- package/dist/service/{EdgeNodeHeartbeatService.d.ts → EdgeNodeSignalClient.d.ts} +3 -3
- package/dist/service/{EdgeNodeHeartbeatService.js → EdgeNodeSignalClient.js} +4 -4
- package/dist/service/EdgeNodeSignalClient.js.map +1 -0
- package/dist/service/PodMigrationService.d.ts +1 -2
- package/dist/service/PodMigrationService.js +1 -2
- package/dist/service/PodMigrationService.js.map +1 -1
- package/dist/storage/SparqlUpdateResourceStore.js +1 -1
- package/dist/storage/SparqlUpdateResourceStore.js.map +1 -1
- package/dist/storage/accessors/MinioDataAccessor.d.ts +6 -0
- package/dist/storage/accessors/MinioDataAccessor.js +10 -0
- package/dist/storage/accessors/MinioDataAccessor.js.map +1 -1
- package/dist/storage/accessors/MinioDataAccessor.jsonld +4 -0
- package/dist/storage/accessors/MixDataAccessor.d.ts +2 -1
- package/dist/storage/accessors/MixDataAccessor.js +12 -1
- package/dist/storage/accessors/MixDataAccessor.js.map +1 -1
- package/dist/storage/accessors/MixDataAccessor.jsonld +19 -0
- package/dist/storage/locking/UrlAwareRedisLocker.d.ts +18 -0
- package/dist/storage/locking/UrlAwareRedisLocker.js +60 -0
- package/dist/storage/locking/UrlAwareRedisLocker.js.map +1 -0
- package/dist/storage/locking/UrlAwareRedisLocker.jsonld +123 -0
- package/dist/storage/quota/UsageRepository.d.ts +41 -8
- package/dist/storage/quota/UsageRepository.js +252 -50
- package/dist/storage/quota/UsageRepository.js.map +1 -1
- package/dist/storage/sparql/ComunicaQuintEngine.d.ts +9 -0
- package/dist/storage/sparql/ComunicaQuintEngine.js +50 -9
- package/dist/storage/sparql/ComunicaQuintEngine.js.map +1 -1
- package/dist/storage/sparql/QueryOptimizer.js +13 -1
- package/dist/storage/sparql/QueryOptimizer.js.map +1 -1
- package/dist/storage/sparql/QuintQuerySource.d.ts +14 -0
- package/dist/storage/sparql/QuintQuerySource.js +152 -1
- package/dist/storage/sparql/QuintQuerySource.js.map +1 -1
- package/dist/storage/sparql/SubgraphQueryEngine.d.ts +1 -0
- package/dist/storage/sparql/SubgraphQueryEngine.js +6 -2
- package/dist/storage/sparql/SubgraphQueryEngine.js.map +1 -1
- package/dist/storage/sparql/SubgraphQueryEngine.jsonld +4 -0
- package/dist/subdomain/SubdomainClient.d.ts +3 -3
- package/dist/subdomain/SubdomainClient.js +1 -1
- package/dist/subdomain/SubdomainClient.js.map +1 -1
- package/dist/subdomain/SubdomainService.d.ts +15 -16
- package/dist/subdomain/SubdomainService.js +80 -54
- package/dist/subdomain/SubdomainService.js.map +1 -1
- package/dist/subdomain/SubdomainService.jsonld +22 -26
- package/dist/supervisor/Supervisor.d.ts +7 -2
- package/dist/supervisor/Supervisor.js +33 -1
- package/dist/supervisor/Supervisor.js.map +1 -1
- package/dist/test-utils/index.d.ts +4 -0
- package/dist/test-utils/index.js +8 -0
- package/dist/test-utils/index.js.map +1 -0
- package/dist/test-utils/no-auth-xpod.d.ts +11 -0
- package/dist/test-utils/no-auth-xpod.js +25 -0
- package/dist/test-utils/no-auth-xpod.js.map +1 -0
- package/dist/test-utils/seed-pod.d.ts +5 -0
- package/dist/test-utils/seed-pod.js +61 -0
- package/dist/test-utils/seed-pod.js.map +1 -0
- package/package.json +23 -5
- package/templates/identity/account/create-pod.html.ejs +110 -0
- package/templates/main.html.ejs +10 -0
- package/dist/api/handlers/DevHandler.d.ts +0 -18
- package/dist/api/handlers/DevHandler.js +0 -276
- package/dist/api/handlers/DevHandler.js.map +0 -1
- package/dist/api/handlers/SignalHandler.d.ts +0 -13
- package/dist/api/handlers/SignalHandler.js +0 -122
- package/dist/api/handlers/SignalHandler.js.map +0 -1
- package/dist/gateway/Proxy.d.ts +0 -24
- package/dist/gateway/Proxy.js +0 -209
- package/dist/gateway/Proxy.js.map +0 -1
- package/dist/gateway/Supervisor.d.ts +0 -2
- package/dist/gateway/Supervisor.js +0 -7
- package/dist/gateway/Supervisor.js.map +0 -1
- package/dist/gateway/port-finder.d.ts +0 -4
- package/dist/gateway/port-finder.js +0 -15
- package/dist/gateway/port-finder.js.map +0 -1
- package/dist/gateway/types.d.ts +0 -1
- package/dist/gateway/types.js +0 -3
- package/dist/gateway/types.js.map +0 -1
- package/dist/http/SignalInterceptHttpHandler.d.ts +0 -24
- package/dist/http/SignalInterceptHttpHandler.js +0 -47
- package/dist/http/SignalInterceptHttpHandler.js.map +0 -1
- package/dist/http/SignalInterceptHttpHandler.jsonld +0 -103
- package/dist/http/admin/EdgeNodeSignalHttpHandler.d.ts +0 -71
- package/dist/http/admin/EdgeNodeSignalHttpHandler.js +0 -674
- package/dist/http/admin/EdgeNodeSignalHttpHandler.js.map +0 -1
- package/dist/http/admin/EdgeNodeSignalHttpHandler.jsonld +0 -406
- package/dist/http/cluster/PodMigrationHttpHandler.jsonld +0 -169
- package/dist/quota/DefaultQuotaService.d.ts +0 -16
- package/dist/quota/DefaultQuotaService.js +0 -37
- package/dist/quota/DefaultQuotaService.js.map +0 -1
- package/dist/quota/DefaultQuotaService.jsonld +0 -85
- package/dist/service/EdgeNodeHeartbeatService.js.map +0 -1
- package/dist/service/PodMigrationService.jsonld +0 -76
- package/dist/storage/MigratableDataAccessor.d.ts +0 -63
- package/dist/storage/MigratableDataAccessor.js +0 -11
- package/dist/storage/MigratableDataAccessor.js.map +0 -1
- package/dist/storage/MigratableDataAccessor.jsonld +0 -60
- package/dist/storage/accessors/TieredMinioDataAccessor.d.ts +0 -150
- package/dist/storage/accessors/TieredMinioDataAccessor.js +0 -582
- package/dist/storage/accessors/TieredMinioDataAccessor.js.map +0 -1
- package/dist/storage/accessors/TieredMinioDataAccessor.jsonld +0 -333
- package/static/app/assets/index.css +0 -1
- package/static/app/assets/main.js +0 -11
|
@@ -2,21 +2,15 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.UsageRepository = void 0;
|
|
4
4
|
const drizzle_orm_1 = require("drizzle-orm");
|
|
5
|
-
const
|
|
5
|
+
const db_1 = require("../../identity/drizzle/db");
|
|
6
6
|
/**
|
|
7
7
|
* Repository for tracking pod and account usage metrics.
|
|
8
|
-
*
|
|
9
|
-
* For local/dev modes, usage tracking should be disabled.
|
|
10
|
-
*
|
|
11
|
-
* TODO: Make UsageRepository database-agnostic to support SQLite in local mode.
|
|
12
|
-
* Required changes:
|
|
13
|
-
* - Replace `sql\`now()\`` with cross-database compatible timestamp (e.g., new Date())
|
|
14
|
-
* - Use Drizzle's database-agnostic transaction API or raw SQL compatible with both
|
|
15
|
-
* - Test with both SQLite and PostgreSQL backends
|
|
8
|
+
* Supports both PostgreSQL and SQLite through unified schema abstraction.
|
|
16
9
|
*/
|
|
17
10
|
class UsageRepository {
|
|
18
11
|
constructor(db) {
|
|
19
12
|
this.db = db;
|
|
13
|
+
this.schema = (0, db_1.getSchema)(db);
|
|
20
14
|
}
|
|
21
15
|
async incrementUsage(accountId, podId, storageDelta, ingressDelta, egressDelta) {
|
|
22
16
|
const normalizedStorage = this.normalizeDelta(storageDelta);
|
|
@@ -56,13 +50,18 @@ class UsageRepository {
|
|
|
56
50
|
}
|
|
57
51
|
async getAccountUsage(accountId) {
|
|
58
52
|
const result = await this.db.select({
|
|
59
|
-
storage:
|
|
60
|
-
ingress:
|
|
61
|
-
egress:
|
|
62
|
-
storageLimit:
|
|
63
|
-
bandwidthLimit:
|
|
64
|
-
|
|
65
|
-
|
|
53
|
+
storage: this.schema.accountUsage.storageBytes,
|
|
54
|
+
ingress: this.schema.accountUsage.ingressBytes,
|
|
55
|
+
egress: this.schema.accountUsage.egressBytes,
|
|
56
|
+
storageLimit: this.schema.accountUsage.storageLimitBytes,
|
|
57
|
+
bandwidthLimit: this.schema.accountUsage.bandwidthLimitBps,
|
|
58
|
+
computeSeconds: this.schema.accountUsage.computeSeconds,
|
|
59
|
+
tokensUsed: this.schema.accountUsage.tokensUsed,
|
|
60
|
+
computeLimitSeconds: this.schema.accountUsage.computeLimitSeconds,
|
|
61
|
+
tokenLimitMonthly: this.schema.accountUsage.tokenLimitMonthly,
|
|
62
|
+
periodStart: this.schema.accountUsage.periodStart,
|
|
63
|
+
}).from(this.schema.accountUsage)
|
|
64
|
+
.where((0, drizzle_orm_1.eq)(this.schema.accountUsage.accountId, accountId));
|
|
66
65
|
if (!result || result.length === 0) {
|
|
67
66
|
return undefined;
|
|
68
67
|
}
|
|
@@ -74,18 +73,28 @@ class UsageRepository {
|
|
|
74
73
|
egressBytes: this.coerceNumber(row.egress),
|
|
75
74
|
storageLimitBytes: this.coerceNullable(row.storageLimit),
|
|
76
75
|
bandwidthLimitBps: this.coerceNullable(row.bandwidthLimit),
|
|
76
|
+
computeSeconds: this.coerceNumber(row.computeSeconds),
|
|
77
|
+
tokensUsed: this.coerceNumber(row.tokensUsed),
|
|
78
|
+
computeLimitSeconds: this.coerceNullable(row.computeLimitSeconds),
|
|
79
|
+
tokenLimitMonthly: this.coerceNullable(row.tokenLimitMonthly),
|
|
80
|
+
periodStart: this.coerceTimestamp(row.periodStart),
|
|
77
81
|
};
|
|
78
82
|
}
|
|
79
83
|
async getPodUsage(podId) {
|
|
80
84
|
const result = await this.db.select({
|
|
81
|
-
accountId:
|
|
82
|
-
storage:
|
|
83
|
-
ingress:
|
|
84
|
-
egress:
|
|
85
|
-
storageLimit:
|
|
86
|
-
bandwidthLimit:
|
|
87
|
-
|
|
88
|
-
|
|
85
|
+
accountId: this.schema.podUsage.accountId,
|
|
86
|
+
storage: this.schema.podUsage.storageBytes,
|
|
87
|
+
ingress: this.schema.podUsage.ingressBytes,
|
|
88
|
+
egress: this.schema.podUsage.egressBytes,
|
|
89
|
+
storageLimit: this.schema.podUsage.storageLimitBytes,
|
|
90
|
+
bandwidthLimit: this.schema.podUsage.bandwidthLimitBps,
|
|
91
|
+
computeSeconds: this.schema.podUsage.computeSeconds,
|
|
92
|
+
tokensUsed: this.schema.podUsage.tokensUsed,
|
|
93
|
+
computeLimitSeconds: this.schema.podUsage.computeLimitSeconds,
|
|
94
|
+
tokenLimitMonthly: this.schema.podUsage.tokenLimitMonthly,
|
|
95
|
+
periodStart: this.schema.podUsage.periodStart,
|
|
96
|
+
}).from(this.schema.podUsage)
|
|
97
|
+
.where((0, drizzle_orm_1.eq)(this.schema.podUsage.podId, podId));
|
|
89
98
|
if (!result || result.length === 0) {
|
|
90
99
|
return undefined;
|
|
91
100
|
}
|
|
@@ -99,6 +108,11 @@ class UsageRepository {
|
|
|
99
108
|
egressBytes: this.coerceNumber(row.egress),
|
|
100
109
|
storageLimitBytes: this.coerceNullable(row.storageLimit),
|
|
101
110
|
bandwidthLimitBps: this.coerceNullable(row.bandwidthLimit),
|
|
111
|
+
computeSeconds: this.coerceNumber(row.computeSeconds),
|
|
112
|
+
tokensUsed: this.coerceNumber(row.tokensUsed),
|
|
113
|
+
computeLimitSeconds: this.coerceNullable(row.computeLimitSeconds),
|
|
114
|
+
tokenLimitMonthly: this.coerceNullable(row.tokenLimitMonthly),
|
|
115
|
+
periodStart: this.coerceTimestamp(row.periodStart),
|
|
102
116
|
};
|
|
103
117
|
}
|
|
104
118
|
async setAccountStorageLimit(accountId, limit) {
|
|
@@ -113,8 +127,118 @@ class UsageRepository {
|
|
|
113
127
|
async setPodBandwidthLimit(podId, accountId, limit) {
|
|
114
128
|
await this.upsertPodUsage(this.db, accountId, podId, undefined, undefined, limit);
|
|
115
129
|
}
|
|
130
|
+
async setAccountComputeLimit(accountId, limit) {
|
|
131
|
+
await this.upsertAccountLimit(this.db, accountId, 'computeLimitSeconds', limit);
|
|
132
|
+
}
|
|
133
|
+
async setAccountTokenLimit(accountId, limit) {
|
|
134
|
+
await this.upsertAccountLimit(this.db, accountId, 'tokenLimitMonthly', limit);
|
|
135
|
+
}
|
|
136
|
+
async setPodComputeLimit(podId, accountId, limit) {
|
|
137
|
+
await this.upsertPodLimit(this.db, accountId, podId, 'computeLimitSeconds', limit);
|
|
138
|
+
}
|
|
139
|
+
async setPodTokenLimit(podId, accountId, limit) {
|
|
140
|
+
await this.upsertPodLimit(this.db, accountId, podId, 'tokenLimitMonthly', limit);
|
|
141
|
+
}
|
|
142
|
+
/**
|
|
143
|
+
* Increment token usage for an account and pod.
|
|
144
|
+
*/
|
|
145
|
+
async incrementTokenUsage(accountId, podId, tokensDelta) {
|
|
146
|
+
const normalized = this.normalizeDelta(tokensDelta);
|
|
147
|
+
if (normalized === 0) {
|
|
148
|
+
return;
|
|
149
|
+
}
|
|
150
|
+
await this.db.transaction(async (tx) => {
|
|
151
|
+
await this.incrementPodTokensWith(tx, accountId, podId, normalized);
|
|
152
|
+
await this.incrementAccountTokensWith(tx, accountId, normalized);
|
|
153
|
+
});
|
|
154
|
+
}
|
|
155
|
+
/**
|
|
156
|
+
* Increment compute usage for an account and pod.
|
|
157
|
+
*/
|
|
158
|
+
async incrementComputeUsage(accountId, podId, secondsDelta) {
|
|
159
|
+
const normalized = this.normalizeDelta(secondsDelta);
|
|
160
|
+
if (normalized === 0) {
|
|
161
|
+
return;
|
|
162
|
+
}
|
|
163
|
+
await this.db.transaction(async (tx) => {
|
|
164
|
+
await this.incrementPodComputeWith(tx, accountId, podId, normalized);
|
|
165
|
+
await this.incrementAccountComputeWith(tx, accountId, normalized);
|
|
166
|
+
});
|
|
167
|
+
}
|
|
168
|
+
async incrementAccountTokensWith(client, accountId, tokensDelta) {
|
|
169
|
+
await client.insert(this.schema.accountUsage)
|
|
170
|
+
.values({
|
|
171
|
+
accountId,
|
|
172
|
+
storageBytes: 0,
|
|
173
|
+
ingressBytes: 0,
|
|
174
|
+
egressBytes: 0,
|
|
175
|
+
tokensUsed: tokensDelta,
|
|
176
|
+
})
|
|
177
|
+
.onConflictDoUpdate({
|
|
178
|
+
target: this.schema.accountUsage.accountId,
|
|
179
|
+
set: {
|
|
180
|
+
tokensUsed: (0, drizzle_orm_1.sql) `${this.schema.accountUsage.tokensUsed} + ${tokensDelta}`,
|
|
181
|
+
updatedAt: this.now(),
|
|
182
|
+
},
|
|
183
|
+
});
|
|
184
|
+
}
|
|
185
|
+
async incrementPodTokensWith(client, accountId, podId, tokensDelta) {
|
|
186
|
+
await client.insert(this.schema.podUsage)
|
|
187
|
+
.values({
|
|
188
|
+
podId,
|
|
189
|
+
accountId,
|
|
190
|
+
storageBytes: 0,
|
|
191
|
+
ingressBytes: 0,
|
|
192
|
+
egressBytes: 0,
|
|
193
|
+
tokensUsed: tokensDelta,
|
|
194
|
+
})
|
|
195
|
+
.onConflictDoUpdate({
|
|
196
|
+
target: this.schema.podUsage.podId,
|
|
197
|
+
set: {
|
|
198
|
+
tokensUsed: (0, drizzle_orm_1.sql) `${this.schema.podUsage.tokensUsed} + ${tokensDelta}`,
|
|
199
|
+
accountId,
|
|
200
|
+
updatedAt: this.now(),
|
|
201
|
+
},
|
|
202
|
+
});
|
|
203
|
+
}
|
|
204
|
+
async incrementAccountComputeWith(client, accountId, secondsDelta) {
|
|
205
|
+
await client.insert(this.schema.accountUsage)
|
|
206
|
+
.values({
|
|
207
|
+
accountId,
|
|
208
|
+
storageBytes: 0,
|
|
209
|
+
ingressBytes: 0,
|
|
210
|
+
egressBytes: 0,
|
|
211
|
+
computeSeconds: secondsDelta,
|
|
212
|
+
})
|
|
213
|
+
.onConflictDoUpdate({
|
|
214
|
+
target: this.schema.accountUsage.accountId,
|
|
215
|
+
set: {
|
|
216
|
+
computeSeconds: (0, drizzle_orm_1.sql) `${this.schema.accountUsage.computeSeconds} + ${secondsDelta}`,
|
|
217
|
+
updatedAt: this.now(),
|
|
218
|
+
},
|
|
219
|
+
});
|
|
220
|
+
}
|
|
221
|
+
async incrementPodComputeWith(client, accountId, podId, secondsDelta) {
|
|
222
|
+
await client.insert(this.schema.podUsage)
|
|
223
|
+
.values({
|
|
224
|
+
podId,
|
|
225
|
+
accountId,
|
|
226
|
+
storageBytes: 0,
|
|
227
|
+
ingressBytes: 0,
|
|
228
|
+
egressBytes: 0,
|
|
229
|
+
computeSeconds: secondsDelta,
|
|
230
|
+
})
|
|
231
|
+
.onConflictDoUpdate({
|
|
232
|
+
target: this.schema.podUsage.podId,
|
|
233
|
+
set: {
|
|
234
|
+
computeSeconds: (0, drizzle_orm_1.sql) `${this.schema.podUsage.computeSeconds} + ${secondsDelta}`,
|
|
235
|
+
accountId,
|
|
236
|
+
updatedAt: this.now(),
|
|
237
|
+
},
|
|
238
|
+
});
|
|
239
|
+
}
|
|
116
240
|
async incrementAccountUsageWith(client, accountId, storageDelta, ingressDelta, egressDelta) {
|
|
117
|
-
await client.insert(
|
|
241
|
+
await client.insert(this.schema.accountUsage)
|
|
118
242
|
.values({
|
|
119
243
|
accountId,
|
|
120
244
|
storageBytes: storageDelta,
|
|
@@ -122,17 +246,17 @@ class UsageRepository {
|
|
|
122
246
|
egressBytes: egressDelta,
|
|
123
247
|
})
|
|
124
248
|
.onConflictDoUpdate({
|
|
125
|
-
target:
|
|
249
|
+
target: this.schema.accountUsage.accountId,
|
|
126
250
|
set: {
|
|
127
|
-
storageBytes: (0, drizzle_orm_1.sql) `${
|
|
128
|
-
ingressBytes: (0, drizzle_orm_1.sql) `${
|
|
129
|
-
egressBytes: (0, drizzle_orm_1.sql) `${
|
|
130
|
-
updatedAt:
|
|
251
|
+
storageBytes: (0, drizzle_orm_1.sql) `${this.schema.accountUsage.storageBytes} + ${storageDelta}`,
|
|
252
|
+
ingressBytes: (0, drizzle_orm_1.sql) `${this.schema.accountUsage.ingressBytes} + ${ingressDelta}`,
|
|
253
|
+
egressBytes: (0, drizzle_orm_1.sql) `${this.schema.accountUsage.egressBytes} + ${egressDelta}`,
|
|
254
|
+
updatedAt: this.now(),
|
|
131
255
|
},
|
|
132
256
|
});
|
|
133
257
|
}
|
|
134
258
|
async incrementPodUsageWith(client, accountId, podId, storageDelta, ingressDelta, egressDelta) {
|
|
135
|
-
await client.insert(
|
|
259
|
+
await client.insert(this.schema.podUsage)
|
|
136
260
|
.values({
|
|
137
261
|
podId,
|
|
138
262
|
accountId,
|
|
@@ -141,13 +265,13 @@ class UsageRepository {
|
|
|
141
265
|
egressBytes: egressDelta,
|
|
142
266
|
})
|
|
143
267
|
.onConflictDoUpdate({
|
|
144
|
-
target:
|
|
268
|
+
target: this.schema.podUsage.podId,
|
|
145
269
|
set: {
|
|
146
|
-
storageBytes: (0, drizzle_orm_1.sql) `${
|
|
147
|
-
ingressBytes: (0, drizzle_orm_1.sql) `${
|
|
148
|
-
egressBytes: (0, drizzle_orm_1.sql) `${
|
|
270
|
+
storageBytes: (0, drizzle_orm_1.sql) `${this.schema.podUsage.storageBytes} + ${storageDelta}`,
|
|
271
|
+
ingressBytes: (0, drizzle_orm_1.sql) `${this.schema.podUsage.ingressBytes} + ${ingressDelta}`,
|
|
272
|
+
egressBytes: (0, drizzle_orm_1.sql) `${this.schema.podUsage.egressBytes} + ${egressDelta}`,
|
|
149
273
|
accountId,
|
|
150
|
-
updatedAt:
|
|
274
|
+
updatedAt: this.now(),
|
|
151
275
|
},
|
|
152
276
|
});
|
|
153
277
|
}
|
|
@@ -166,7 +290,7 @@ class UsageRepository {
|
|
|
166
290
|
insertValues.bandwidthLimitBps = bandwidthLimit;
|
|
167
291
|
}
|
|
168
292
|
const updateSet = {
|
|
169
|
-
updatedAt:
|
|
293
|
+
updatedAt: this.now(),
|
|
170
294
|
};
|
|
171
295
|
if (typeof storageValue === 'number') {
|
|
172
296
|
updateSet.storageBytes = storageValue;
|
|
@@ -177,10 +301,10 @@ class UsageRepository {
|
|
|
177
301
|
if (bandwidthLimit !== undefined) {
|
|
178
302
|
updateSet.bandwidthLimitBps = bandwidthLimit;
|
|
179
303
|
}
|
|
180
|
-
await client.insert(
|
|
304
|
+
await client.insert(this.schema.accountUsage)
|
|
181
305
|
.values(insertValues)
|
|
182
306
|
.onConflictDoUpdate({
|
|
183
|
-
target:
|
|
307
|
+
target: this.schema.accountUsage.accountId,
|
|
184
308
|
set: updateSet,
|
|
185
309
|
});
|
|
186
310
|
}
|
|
@@ -201,7 +325,7 @@ class UsageRepository {
|
|
|
201
325
|
}
|
|
202
326
|
const updateSet = {
|
|
203
327
|
accountId,
|
|
204
|
-
updatedAt:
|
|
328
|
+
updatedAt: this.now(),
|
|
205
329
|
};
|
|
206
330
|
if (typeof storageValue === 'number') {
|
|
207
331
|
updateSet.storageBytes = storageValue;
|
|
@@ -212,23 +336,72 @@ class UsageRepository {
|
|
|
212
336
|
if (bandwidthLimit !== undefined) {
|
|
213
337
|
updateSet.bandwidthLimitBps = bandwidthLimit;
|
|
214
338
|
}
|
|
215
|
-
await client.insert(
|
|
339
|
+
await client.insert(this.schema.podUsage)
|
|
216
340
|
.values(insertValues)
|
|
217
341
|
.onConflictDoUpdate({
|
|
218
|
-
target:
|
|
342
|
+
target: this.schema.podUsage.podId,
|
|
219
343
|
set: updateSet,
|
|
220
344
|
});
|
|
221
345
|
}
|
|
346
|
+
/**
|
|
347
|
+
* Generic account limit setter for compute/token limits.
|
|
348
|
+
*/
|
|
349
|
+
async upsertAccountLimit(client, accountId, field, value) {
|
|
350
|
+
const insertValues = {
|
|
351
|
+
accountId,
|
|
352
|
+
storageBytes: 0,
|
|
353
|
+
ingressBytes: 0,
|
|
354
|
+
egressBytes: 0,
|
|
355
|
+
[field]: value,
|
|
356
|
+
};
|
|
357
|
+
await client.insert(this.schema.accountUsage)
|
|
358
|
+
.values(insertValues)
|
|
359
|
+
.onConflictDoUpdate({
|
|
360
|
+
target: this.schema.accountUsage.accountId,
|
|
361
|
+
set: {
|
|
362
|
+
[field]: value,
|
|
363
|
+
updatedAt: this.now(),
|
|
364
|
+
},
|
|
365
|
+
});
|
|
366
|
+
}
|
|
367
|
+
/**
|
|
368
|
+
* Generic pod limit setter for compute/token limits.
|
|
369
|
+
*/
|
|
370
|
+
async upsertPodLimit(client, accountId, podId, field, value) {
|
|
371
|
+
const insertValues = {
|
|
372
|
+
podId,
|
|
373
|
+
accountId,
|
|
374
|
+
storageBytes: 0,
|
|
375
|
+
ingressBytes: 0,
|
|
376
|
+
egressBytes: 0,
|
|
377
|
+
[field]: value,
|
|
378
|
+
};
|
|
379
|
+
await client.insert(this.schema.podUsage)
|
|
380
|
+
.values(insertValues)
|
|
381
|
+
.onConflictDoUpdate({
|
|
382
|
+
target: this.schema.podUsage.podId,
|
|
383
|
+
set: {
|
|
384
|
+
accountId,
|
|
385
|
+
[field]: value,
|
|
386
|
+
updatedAt: this.now(),
|
|
387
|
+
},
|
|
388
|
+
});
|
|
389
|
+
}
|
|
222
390
|
async getPodUsageWith(client, podId) {
|
|
223
391
|
const result = await client.select({
|
|
224
|
-
accountId:
|
|
225
|
-
storage:
|
|
226
|
-
ingress:
|
|
227
|
-
egress:
|
|
228
|
-
storageLimit:
|
|
229
|
-
bandwidthLimit:
|
|
230
|
-
|
|
231
|
-
|
|
392
|
+
accountId: this.schema.podUsage.accountId,
|
|
393
|
+
storage: this.schema.podUsage.storageBytes,
|
|
394
|
+
ingress: this.schema.podUsage.ingressBytes,
|
|
395
|
+
egress: this.schema.podUsage.egressBytes,
|
|
396
|
+
storageLimit: this.schema.podUsage.storageLimitBytes,
|
|
397
|
+
bandwidthLimit: this.schema.podUsage.bandwidthLimitBps,
|
|
398
|
+
computeSeconds: this.schema.podUsage.computeSeconds,
|
|
399
|
+
tokensUsed: this.schema.podUsage.tokensUsed,
|
|
400
|
+
computeLimitSeconds: this.schema.podUsage.computeLimitSeconds,
|
|
401
|
+
tokenLimitMonthly: this.schema.podUsage.tokenLimitMonthly,
|
|
402
|
+
periodStart: this.schema.podUsage.periodStart,
|
|
403
|
+
}).from(this.schema.podUsage)
|
|
404
|
+
.where((0, drizzle_orm_1.eq)(this.schema.podUsage.podId, podId));
|
|
232
405
|
if (!result || result.length === 0) {
|
|
233
406
|
return undefined;
|
|
234
407
|
}
|
|
@@ -242,6 +415,11 @@ class UsageRepository {
|
|
|
242
415
|
egressBytes: this.coerceNumber(row.egress),
|
|
243
416
|
storageLimitBytes: this.coerceNullable(row.storageLimit),
|
|
244
417
|
bandwidthLimitBps: this.coerceNullable(row.bandwidthLimit),
|
|
418
|
+
computeSeconds: this.coerceNumber(row.computeSeconds),
|
|
419
|
+
tokensUsed: this.coerceNumber(row.tokensUsed),
|
|
420
|
+
computeLimitSeconds: this.coerceNullable(row.computeLimitSeconds),
|
|
421
|
+
tokenLimitMonthly: this.coerceNullable(row.tokenLimitMonthly),
|
|
422
|
+
periodStart: this.coerceTimestamp(row.periodStart),
|
|
245
423
|
};
|
|
246
424
|
}
|
|
247
425
|
normalizeDelta(value) {
|
|
@@ -273,6 +451,30 @@ class UsageRepository {
|
|
|
273
451
|
}
|
|
274
452
|
return Math.trunc(numeric);
|
|
275
453
|
}
|
|
454
|
+
/**
|
|
455
|
+
* Coerce timestamp value to Unix timestamp (seconds).
|
|
456
|
+
* Handles Date objects (from PG) and numbers (from SQLite).
|
|
457
|
+
*/
|
|
458
|
+
coerceTimestamp(value) {
|
|
459
|
+
if (value === null || value === undefined) {
|
|
460
|
+
return null;
|
|
461
|
+
}
|
|
462
|
+
if (value instanceof Date) {
|
|
463
|
+
return Math.floor(value.getTime() / 1000);
|
|
464
|
+
}
|
|
465
|
+
if (typeof value === 'number') {
|
|
466
|
+
return value;
|
|
467
|
+
}
|
|
468
|
+
return null;
|
|
469
|
+
}
|
|
470
|
+
/**
|
|
471
|
+
* Get the current timestamp in the format expected by the database.
|
|
472
|
+
* PG expects Date objects, SQLite expects Unix timestamps (seconds).
|
|
473
|
+
*/
|
|
474
|
+
now() {
|
|
475
|
+
const timestamp = new Date();
|
|
476
|
+
return (0, db_1.isDatabaseSqlite)(this.db) ? Math.floor(timestamp.getTime() / 1000) : timestamp;
|
|
477
|
+
}
|
|
276
478
|
}
|
|
277
479
|
exports.UsageRepository = UsageRepository;
|
|
278
480
|
//# sourceMappingURL=UsageRepository.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"UsageRepository.js","sourceRoot":"","sources":["../../../src/storage/quota/UsageRepository.ts"],"names":[],"mappings":"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","sourcesContent":["import { sql, eq } from 'drizzle-orm';\nimport type { IdentityDatabase } from '../../identity/drizzle/db';\nimport type { NodePgTransaction } from 'drizzle-orm/node-postgres/session';\nimport { accountUsage, podUsage } from '../../identity/drizzle/schema';\n\ntype DbClient = IdentityDatabase | NodePgTransaction<any, any>;\n\nexport interface AccountUsageRecord {\n accountId: string;\n storageBytes: number;\n ingressBytes: number;\n egressBytes: number;\n storageLimitBytes?: number | null;\n bandwidthLimitBps?: number | null;\n}\n\nexport interface PodUsageRecord extends AccountUsageRecord {\n podId: string;\n}\n\n/**\n * Repository for tracking pod and account usage metrics.\n * NOTE: This repository only supports PostgreSQL. SQLite is not supported.\n * For local/dev modes, usage tracking should be disabled.\n *\n * TODO: Make UsageRepository database-agnostic to support SQLite in local mode.\n * Required changes:\n * - Replace `sql\\`now()\\`` with cross-database compatible timestamp (e.g., new Date())\n * - Use Drizzle's database-agnostic transaction API or raw SQL compatible with both\n * - Test with both SQLite and PostgreSQL backends\n */\nexport class UsageRepository {\n public constructor(private readonly db: IdentityDatabase) {}\n\n public async incrementUsage(accountId: string, podId: string, storageDelta: number, ingressDelta: number, egressDelta: number): Promise<void> {\n const normalizedStorage = this.normalizeDelta(storageDelta);\n const normalizedIngress = this.normalizeDelta(ingressDelta);\n const normalizedEgress = this.normalizeDelta(egressDelta);\n if (normalizedStorage === 0 && normalizedIngress === 0 && normalizedEgress === 0) {\n return;\n }\n await this.db.transaction(async (tx: IdentityDatabase) => {\n await this.incrementPodUsageWith(tx, accountId, podId, normalizedStorage, normalizedIngress, normalizedEgress);\n await this.incrementAccountUsageWith(tx, accountId, normalizedStorage, normalizedIngress, normalizedEgress);\n });\n }\n\n public async incrementBandwidth(accountId: string, podId: string, ingressDelta: number, egressDelta: number): Promise<void> {\n await this.incrementUsage(accountId, podId, 0, ingressDelta, egressDelta);\n }\n\n public async setPodStorage(accountId: string, podId: string, storageBytes: number): Promise<void> {\n const normalized = this.normalizeValue(storageBytes);\n await this.db.transaction(async (tx: IdentityDatabase) => {\n const current = await this.getPodUsageWith(tx, podId);\n const owningAccountId = current?.accountId ?? accountId;\n const previousStorage = current?.storageBytes ?? 0;\n const delta = normalized - previousStorage;\n\n await this.upsertPodUsage(tx, owningAccountId, podId, normalized);\n if (delta !== 0) {\n await this.incrementAccountUsageWith(tx, owningAccountId, delta, 0, 0);\n }\n });\n }\n\n public async setAccountStorage(accountId: string, storageBytes: number): Promise<void> {\n const normalized = this.normalizeValue(storageBytes);\n await this.db.transaction(async (tx: IdentityDatabase) => {\n await this.upsertAccountUsage(tx, accountId, normalized);\n // Adjust pod rows proportionally is undefined behaviour here, so only account-level storage is updated.\n // Pods should be updated independently by their respective setters.\n });\n }\n\n public async getAccountUsage(accountId: string): Promise<AccountUsageRecord | undefined> {\n const result = await this.db.select({\n storage: accountUsage.storageBytes,\n ingress: accountUsage.ingressBytes,\n egress: accountUsage.egressBytes,\n storageLimit: accountUsage.storageLimitBytes,\n bandwidthLimit: accountUsage.bandwidthLimitBps,\n }).from(accountUsage)\n .where(eq(accountUsage.accountId, accountId));\n if (!result || result.length === 0) {\n return undefined;\n }\n const row = result[0];\n return {\n accountId,\n storageBytes: this.coerceNumber(row.storage),\n ingressBytes: this.coerceNumber(row.ingress),\n egressBytes: this.coerceNumber(row.egress),\n storageLimitBytes: this.coerceNullable(row.storageLimit),\n bandwidthLimitBps: this.coerceNullable(row.bandwidthLimit),\n };\n }\n\n public async getPodUsage(podId: string): Promise<PodUsageRecord | undefined> {\n const result = await this.db.select({\n accountId: podUsage.accountId,\n storage: podUsage.storageBytes,\n ingress: podUsage.ingressBytes,\n egress: podUsage.egressBytes,\n storageLimit: podUsage.storageLimitBytes,\n bandwidthLimit: podUsage.bandwidthLimitBps,\n }).from(podUsage)\n .where(eq(podUsage.podId, podId));\n if (!result || result.length === 0) {\n return undefined;\n }\n const row = result[0];\n const accountId = String(row.accountId);\n return {\n podId,\n accountId,\n storageBytes: this.coerceNumber(row.storage),\n ingressBytes: this.coerceNumber(row.ingress),\n egressBytes: this.coerceNumber(row.egress),\n storageLimitBytes: this.coerceNullable(row.storageLimit),\n bandwidthLimitBps: this.coerceNullable(row.bandwidthLimit),\n };\n }\n\n public async setAccountStorageLimit(accountId: string, limit: number | null): Promise<void> {\n await this.upsertAccountUsage(this.db, accountId, undefined, limit, undefined);\n }\n\n public async setPodStorageLimit(podId: string, accountId: string, limit: number | null): Promise<void> {\n await this.upsertPodUsage(this.db, accountId, podId, undefined, limit, undefined);\n }\n\n public async setAccountBandwidthLimit(accountId: string, limit: number | null): Promise<void> {\n await this.upsertAccountUsage(this.db, accountId, undefined, undefined, limit);\n }\n\n public async setPodBandwidthLimit(podId: string, accountId: string, limit: number | null): Promise<void> {\n await this.upsertPodUsage(this.db, accountId, podId, undefined, undefined, limit);\n }\n\n private async incrementAccountUsageWith(client: DbClient, accountId: string, storageDelta: number, ingressDelta: number, egressDelta: number): Promise<void> {\n await client.insert(accountUsage)\n .values({\n accountId,\n storageBytes: storageDelta,\n ingressBytes: ingressDelta,\n egressBytes: egressDelta,\n })\n .onConflictDoUpdate({\n target: accountUsage.accountId,\n set: {\n storageBytes: sql`${accountUsage.storageBytes} + ${storageDelta}`,\n ingressBytes: sql`${accountUsage.ingressBytes} + ${ingressDelta}`,\n egressBytes: sql`${accountUsage.egressBytes} + ${egressDelta}`,\n updatedAt: sql`now()`,\n },\n });\n }\n\n private async incrementPodUsageWith(client: DbClient, accountId: string, podId: string, storageDelta: number, ingressDelta: number, egressDelta: number): Promise<void> {\n await client.insert(podUsage)\n .values({\n podId,\n accountId,\n storageBytes: storageDelta,\n ingressBytes: ingressDelta,\n egressBytes: egressDelta,\n })\n .onConflictDoUpdate({\n target: podUsage.podId,\n set: {\n storageBytes: sql`${podUsage.storageBytes} + ${storageDelta}`,\n ingressBytes: sql`${podUsage.ingressBytes} + ${ingressDelta}`,\n egressBytes: sql`${podUsage.egressBytes} + ${egressDelta}`,\n accountId,\n updatedAt: sql`now()`,\n },\n });\n }\n\n private async upsertAccountUsage(client: DbClient, accountId: string, storageBytes?: number, storageLimit?: number | null, bandwidthLimit?: number | null): Promise<void> {\n const storageValue = typeof storageBytes === 'number' ? this.normalizeValue(storageBytes) : undefined;\n const insertValues: Record<string, unknown> = {\n accountId,\n storageBytes: storageValue ?? 0,\n ingressBytes: 0,\n egressBytes: 0,\n };\n if (storageLimit !== undefined) {\n insertValues.storageLimitBytes = storageLimit;\n }\n if (bandwidthLimit !== undefined) {\n insertValues.bandwidthLimitBps = bandwidthLimit;\n }\n const updateSet: Record<string, unknown> = {\n updatedAt: sql`now()`,\n };\n if (typeof storageValue === 'number') {\n updateSet.storageBytes = storageValue;\n }\n if (storageLimit !== undefined) {\n updateSet.storageLimitBytes = storageLimit;\n }\n if (bandwidthLimit !== undefined) {\n updateSet.bandwidthLimitBps = bandwidthLimit;\n }\n await client.insert(accountUsage)\n .values(insertValues)\n .onConflictDoUpdate({\n target: accountUsage.accountId,\n set: updateSet,\n });\n }\n\n private async upsertPodUsage(client: DbClient, accountId: string, podId: string, storageBytes?: number, storageLimit?: number | null, bandwidthLimit?: number | null): Promise<void> {\n const storageValue = typeof storageBytes === 'number' ? this.normalizeValue(storageBytes) : undefined;\n const insertValues: Record<string, unknown> = {\n podId,\n accountId,\n storageBytes: storageValue ?? 0,\n ingressBytes: 0,\n egressBytes: 0,\n };\n if (storageLimit !== undefined) {\n insertValues.storageLimitBytes = storageLimit;\n }\n if (bandwidthLimit !== undefined) {\n insertValues.bandwidthLimitBps = bandwidthLimit;\n }\n const updateSet: Record<string, unknown> = {\n accountId,\n updatedAt: sql`now()`,\n };\n if (typeof storageValue === 'number') {\n updateSet.storageBytes = storageValue;\n }\n if (storageLimit !== undefined) {\n updateSet.storageLimitBytes = storageLimit;\n }\n if (bandwidthLimit !== undefined) {\n updateSet.bandwidthLimitBps = bandwidthLimit;\n }\n await client.insert(podUsage)\n .values(insertValues)\n .onConflictDoUpdate({\n target: podUsage.podId,\n set: updateSet,\n });\n }\n\n private async getPodUsageWith(client: DbClient, podId: string): Promise<PodUsageRecord | undefined> {\n const result = await client.select({\n accountId: podUsage.accountId,\n storage: podUsage.storageBytes,\n ingress: podUsage.ingressBytes,\n egress: podUsage.egressBytes,\n storageLimit: podUsage.storageLimitBytes,\n bandwidthLimit: podUsage.bandwidthLimitBps,\n }).from(podUsage)\n .where(eq(podUsage.podId, podId));\n if (!result || result.length === 0) {\n return undefined;\n }\n const row = result[0];\n const accountId = String(row.accountId);\n return {\n podId,\n accountId,\n storageBytes: this.coerceNumber(row.storage),\n ingressBytes: this.coerceNumber(row.ingress),\n egressBytes: this.coerceNumber(row.egress),\n storageLimitBytes: this.coerceNullable(row.storageLimit),\n bandwidthLimitBps: this.coerceNullable(row.bandwidthLimit),\n };\n }\n\n private normalizeDelta(value: number): number {\n if (!Number.isFinite(value) || value === 0) {\n return 0;\n }\n return Math.trunc(value);\n }\n\n private normalizeValue(value: number): number {\n if (!Number.isFinite(value) || value <= 0) {\n return 0;\n }\n return Math.max(0, Math.trunc(value));\n }\n\n private coerceNumber(value: unknown): number {\n const numeric = Number(value ?? 0);\n return Number.isFinite(numeric) ? numeric : 0;\n }\n\n private coerceNullable(value: unknown): number | null | undefined {\n if (value === undefined) {\n return undefined;\n }\n if (value === null) {\n return null;\n }\n const numeric = Number(value);\n if (!Number.isFinite(numeric)) {\n return null;\n }\n return Math.trunc(numeric);\n }\n}\n"]}
|
|
1
|
+
{"version":3,"file":"UsageRepository.js","sourceRoot":"","sources":["../../../src/storage/quota/UsageRepository.ts"],"names":[],"mappings":"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","sourcesContent":["import { sql, eq } from 'drizzle-orm';\nimport type { IdentityDatabase } from '../../identity/drizzle/db';\nimport { getSchema, isDatabaseSqlite } from '../../identity/drizzle/db';\nimport type { NodePgTransaction } from 'drizzle-orm/node-postgres/session';\n\ntype DbClient = IdentityDatabase | NodePgTransaction<any, any>;\n\nexport interface AccountUsageRecord {\n accountId: string;\n storageBytes: number;\n ingressBytes: number;\n egressBytes: number;\n storageLimitBytes?: number | null;\n bandwidthLimitBps?: number | null;\n computeSeconds: number;\n tokensUsed: number;\n computeLimitSeconds?: number | null;\n tokenLimitMonthly?: number | null;\n periodStart?: number | null;\n}\n\nexport interface PodUsageRecord extends AccountUsageRecord {\n podId: string;\n}\n\n/**\n * Repository for tracking pod and account usage metrics.\n * Supports both PostgreSQL and SQLite through unified schema abstraction.\n */\nexport class UsageRepository {\n private readonly schema: ReturnType<typeof getSchema>;\n\n public constructor(private readonly db: IdentityDatabase) {\n this.schema = getSchema(db);\n }\n\n public async incrementUsage(accountId: string, podId: string, storageDelta: number, ingressDelta: number, egressDelta: number): Promise<void> {\n const normalizedStorage = this.normalizeDelta(storageDelta);\n const normalizedIngress = this.normalizeDelta(ingressDelta);\n const normalizedEgress = this.normalizeDelta(egressDelta);\n if (normalizedStorage === 0 && normalizedIngress === 0 && normalizedEgress === 0) {\n return;\n }\n await this.db.transaction(async (tx: IdentityDatabase) => {\n await this.incrementPodUsageWith(tx, accountId, podId, normalizedStorage, normalizedIngress, normalizedEgress);\n await this.incrementAccountUsageWith(tx, accountId, normalizedStorage, normalizedIngress, normalizedEgress);\n });\n }\n\n public async incrementBandwidth(accountId: string, podId: string, ingressDelta: number, egressDelta: number): Promise<void> {\n await this.incrementUsage(accountId, podId, 0, ingressDelta, egressDelta);\n }\n\n public async setPodStorage(accountId: string, podId: string, storageBytes: number): Promise<void> {\n const normalized = this.normalizeValue(storageBytes);\n await this.db.transaction(async (tx: IdentityDatabase) => {\n const current = await this.getPodUsageWith(tx, podId);\n const owningAccountId = current?.accountId ?? accountId;\n const previousStorage = current?.storageBytes ?? 0;\n const delta = normalized - previousStorage;\n\n await this.upsertPodUsage(tx, owningAccountId, podId, normalized);\n if (delta !== 0) {\n await this.incrementAccountUsageWith(tx, owningAccountId, delta, 0, 0);\n }\n });\n }\n\n public async setAccountStorage(accountId: string, storageBytes: number): Promise<void> {\n const normalized = this.normalizeValue(storageBytes);\n await this.db.transaction(async (tx: IdentityDatabase) => {\n await this.upsertAccountUsage(tx, accountId, normalized);\n // Adjust pod rows proportionally is undefined behaviour here, so only account-level storage is updated.\n // Pods should be updated independently by their respective setters.\n });\n }\n\n public async getAccountUsage(accountId: string): Promise<AccountUsageRecord | undefined> {\n const result = await this.db.select({\n storage: this.schema.accountUsage.storageBytes,\n ingress: this.schema.accountUsage.ingressBytes,\n egress: this.schema.accountUsage.egressBytes,\n storageLimit: this.schema.accountUsage.storageLimitBytes,\n bandwidthLimit: this.schema.accountUsage.bandwidthLimitBps,\n computeSeconds: this.schema.accountUsage.computeSeconds,\n tokensUsed: this.schema.accountUsage.tokensUsed,\n computeLimitSeconds: this.schema.accountUsage.computeLimitSeconds,\n tokenLimitMonthly: this.schema.accountUsage.tokenLimitMonthly,\n periodStart: this.schema.accountUsage.periodStart,\n }).from(this.schema.accountUsage)\n .where(eq(this.schema.accountUsage.accountId, accountId));\n if (!result || result.length === 0) {\n return undefined;\n }\n const row = result[0];\n return {\n accountId,\n storageBytes: this.coerceNumber(row.storage),\n ingressBytes: this.coerceNumber(row.ingress),\n egressBytes: this.coerceNumber(row.egress),\n storageLimitBytes: this.coerceNullable(row.storageLimit),\n bandwidthLimitBps: this.coerceNullable(row.bandwidthLimit),\n computeSeconds: this.coerceNumber(row.computeSeconds),\n tokensUsed: this.coerceNumber(row.tokensUsed),\n computeLimitSeconds: this.coerceNullable(row.computeLimitSeconds),\n tokenLimitMonthly: this.coerceNullable(row.tokenLimitMonthly),\n periodStart: this.coerceTimestamp(row.periodStart),\n };\n }\n\n public async getPodUsage(podId: string): Promise<PodUsageRecord | undefined> {\n const result = await this.db.select({\n accountId: this.schema.podUsage.accountId,\n storage: this.schema.podUsage.storageBytes,\n ingress: this.schema.podUsage.ingressBytes,\n egress: this.schema.podUsage.egressBytes,\n storageLimit: this.schema.podUsage.storageLimitBytes,\n bandwidthLimit: this.schema.podUsage.bandwidthLimitBps,\n computeSeconds: this.schema.podUsage.computeSeconds,\n tokensUsed: this.schema.podUsage.tokensUsed,\n computeLimitSeconds: this.schema.podUsage.computeLimitSeconds,\n tokenLimitMonthly: this.schema.podUsage.tokenLimitMonthly,\n periodStart: this.schema.podUsage.periodStart,\n }).from(this.schema.podUsage)\n .where(eq(this.schema.podUsage.podId, podId));\n if (!result || result.length === 0) {\n return undefined;\n }\n const row = result[0];\n const accountId = String(row.accountId);\n return {\n podId,\n accountId,\n storageBytes: this.coerceNumber(row.storage),\n ingressBytes: this.coerceNumber(row.ingress),\n egressBytes: this.coerceNumber(row.egress),\n storageLimitBytes: this.coerceNullable(row.storageLimit),\n bandwidthLimitBps: this.coerceNullable(row.bandwidthLimit),\n computeSeconds: this.coerceNumber(row.computeSeconds),\n tokensUsed: this.coerceNumber(row.tokensUsed),\n computeLimitSeconds: this.coerceNullable(row.computeLimitSeconds),\n tokenLimitMonthly: this.coerceNullable(row.tokenLimitMonthly),\n periodStart: this.coerceTimestamp(row.periodStart),\n };\n }\n\n public async setAccountStorageLimit(accountId: string, limit: number | null): Promise<void> {\n await this.upsertAccountUsage(this.db, accountId, undefined, limit, undefined);\n }\n\n public async setPodStorageLimit(podId: string, accountId: string, limit: number | null): Promise<void> {\n await this.upsertPodUsage(this.db, accountId, podId, undefined, limit, undefined);\n }\n\n public async setAccountBandwidthLimit(accountId: string, limit: number | null): Promise<void> {\n await this.upsertAccountUsage(this.db, accountId, undefined, undefined, limit);\n }\n\n public async setPodBandwidthLimit(podId: string, accountId: string, limit: number | null): Promise<void> {\n await this.upsertPodUsage(this.db, accountId, podId, undefined, undefined, limit);\n }\n\n public async setAccountComputeLimit(accountId: string, limit: number | null): Promise<void> {\n await this.upsertAccountLimit(this.db, accountId, 'computeLimitSeconds', limit);\n }\n\n public async setAccountTokenLimit(accountId: string, limit: number | null): Promise<void> {\n await this.upsertAccountLimit(this.db, accountId, 'tokenLimitMonthly', limit);\n }\n\n public async setPodComputeLimit(podId: string, accountId: string, limit: number | null): Promise<void> {\n await this.upsertPodLimit(this.db, accountId, podId, 'computeLimitSeconds', limit);\n }\n\n public async setPodTokenLimit(podId: string, accountId: string, limit: number | null): Promise<void> {\n await this.upsertPodLimit(this.db, accountId, podId, 'tokenLimitMonthly', limit);\n }\n\n /**\n * Increment token usage for an account and pod.\n */\n public async incrementTokenUsage(accountId: string, podId: string, tokensDelta: number): Promise<void> {\n const normalized = this.normalizeDelta(tokensDelta);\n if (normalized === 0) {\n return;\n }\n await this.db.transaction(async (tx: IdentityDatabase) => {\n await this.incrementPodTokensWith(tx, accountId, podId, normalized);\n await this.incrementAccountTokensWith(tx, accountId, normalized);\n });\n }\n\n /**\n * Increment compute usage for an account and pod.\n */\n public async incrementComputeUsage(accountId: string, podId: string, secondsDelta: number): Promise<void> {\n const normalized = this.normalizeDelta(secondsDelta);\n if (normalized === 0) {\n return;\n }\n await this.db.transaction(async (tx: IdentityDatabase) => {\n await this.incrementPodComputeWith(tx, accountId, podId, normalized);\n await this.incrementAccountComputeWith(tx, accountId, normalized);\n });\n }\n\n private async incrementAccountTokensWith(client: DbClient, accountId: string, tokensDelta: number): Promise<void> {\n await client.insert(this.schema.accountUsage)\n .values({\n accountId,\n storageBytes: 0,\n ingressBytes: 0,\n egressBytes: 0,\n tokensUsed: tokensDelta,\n })\n .onConflictDoUpdate({\n target: this.schema.accountUsage.accountId,\n set: {\n tokensUsed: sql`${this.schema.accountUsage.tokensUsed} + ${tokensDelta}`,\n updatedAt: this.now(),\n },\n });\n }\n\n private async incrementPodTokensWith(client: DbClient, accountId: string, podId: string, tokensDelta: number): Promise<void> {\n await client.insert(this.schema.podUsage)\n .values({\n podId,\n accountId,\n storageBytes: 0,\n ingressBytes: 0,\n egressBytes: 0,\n tokensUsed: tokensDelta,\n })\n .onConflictDoUpdate({\n target: this.schema.podUsage.podId,\n set: {\n tokensUsed: sql`${this.schema.podUsage.tokensUsed} + ${tokensDelta}`,\n accountId,\n updatedAt: this.now(),\n },\n });\n }\n\n private async incrementAccountComputeWith(client: DbClient, accountId: string, secondsDelta: number): Promise<void> {\n await client.insert(this.schema.accountUsage)\n .values({\n accountId,\n storageBytes: 0,\n ingressBytes: 0,\n egressBytes: 0,\n computeSeconds: secondsDelta,\n })\n .onConflictDoUpdate({\n target: this.schema.accountUsage.accountId,\n set: {\n computeSeconds: sql`${this.schema.accountUsage.computeSeconds} + ${secondsDelta}`,\n updatedAt: this.now(),\n },\n });\n }\n\n private async incrementPodComputeWith(client: DbClient, accountId: string, podId: string, secondsDelta: number): Promise<void> {\n await client.insert(this.schema.podUsage)\n .values({\n podId,\n accountId,\n storageBytes: 0,\n ingressBytes: 0,\n egressBytes: 0,\n computeSeconds: secondsDelta,\n })\n .onConflictDoUpdate({\n target: this.schema.podUsage.podId,\n set: {\n computeSeconds: sql`${this.schema.podUsage.computeSeconds} + ${secondsDelta}`,\n accountId,\n updatedAt: this.now(),\n },\n });\n }\n\n private async incrementAccountUsageWith(client: DbClient, accountId: string, storageDelta: number, ingressDelta: number, egressDelta: number): Promise<void> {\n await client.insert(this.schema.accountUsage)\n .values({\n accountId,\n storageBytes: storageDelta,\n ingressBytes: ingressDelta,\n egressBytes: egressDelta,\n })\n .onConflictDoUpdate({\n target: this.schema.accountUsage.accountId,\n set: {\n storageBytes: sql`${this.schema.accountUsage.storageBytes} + ${storageDelta}`,\n ingressBytes: sql`${this.schema.accountUsage.ingressBytes} + ${ingressDelta}`,\n egressBytes: sql`${this.schema.accountUsage.egressBytes} + ${egressDelta}`,\n updatedAt: this.now(),\n },\n });\n }\n\n private async incrementPodUsageWith(client: DbClient, accountId: string, podId: string, storageDelta: number, ingressDelta: number, egressDelta: number): Promise<void> {\n await client.insert(this.schema.podUsage)\n .values({\n podId,\n accountId,\n storageBytes: storageDelta,\n ingressBytes: ingressDelta,\n egressBytes: egressDelta,\n })\n .onConflictDoUpdate({\n target: this.schema.podUsage.podId,\n set: {\n storageBytes: sql`${this.schema.podUsage.storageBytes} + ${storageDelta}`,\n ingressBytes: sql`${this.schema.podUsage.ingressBytes} + ${ingressDelta}`,\n egressBytes: sql`${this.schema.podUsage.egressBytes} + ${egressDelta}`,\n accountId,\n updatedAt: this.now(),\n },\n });\n }\n\n private async upsertAccountUsage(client: DbClient, accountId: string, storageBytes?: number, storageLimit?: number | null, bandwidthLimit?: number | null): Promise<void> {\n const storageValue = typeof storageBytes === 'number' ? this.normalizeValue(storageBytes) : undefined;\n const insertValues: Record<string, unknown> = {\n accountId,\n storageBytes: storageValue ?? 0,\n ingressBytes: 0,\n egressBytes: 0,\n };\n if (storageLimit !== undefined) {\n insertValues.storageLimitBytes = storageLimit;\n }\n if (bandwidthLimit !== undefined) {\n insertValues.bandwidthLimitBps = bandwidthLimit;\n }\n const updateSet: Record<string, unknown> = {\n updatedAt: this.now(),\n };\n if (typeof storageValue === 'number') {\n updateSet.storageBytes = storageValue;\n }\n if (storageLimit !== undefined) {\n updateSet.storageLimitBytes = storageLimit;\n }\n if (bandwidthLimit !== undefined) {\n updateSet.bandwidthLimitBps = bandwidthLimit;\n }\n await client.insert(this.schema.accountUsage)\n .values(insertValues)\n .onConflictDoUpdate({\n target: this.schema.accountUsage.accountId,\n set: updateSet,\n });\n }\n\n private async upsertPodUsage(client: DbClient, accountId: string, podId: string, storageBytes?: number, storageLimit?: number | null, bandwidthLimit?: number | null): Promise<void> {\n const storageValue = typeof storageBytes === 'number' ? this.normalizeValue(storageBytes) : undefined;\n const insertValues: Record<string, unknown> = {\n podId,\n accountId,\n storageBytes: storageValue ?? 0,\n ingressBytes: 0,\n egressBytes: 0,\n };\n if (storageLimit !== undefined) {\n insertValues.storageLimitBytes = storageLimit;\n }\n if (bandwidthLimit !== undefined) {\n insertValues.bandwidthLimitBps = bandwidthLimit;\n }\n const updateSet: Record<string, unknown> = {\n accountId,\n updatedAt: this.now(),\n };\n if (typeof storageValue === 'number') {\n updateSet.storageBytes = storageValue;\n }\n if (storageLimit !== undefined) {\n updateSet.storageLimitBytes = storageLimit;\n }\n if (bandwidthLimit !== undefined) {\n updateSet.bandwidthLimitBps = bandwidthLimit;\n }\n await client.insert(this.schema.podUsage)\n .values(insertValues)\n .onConflictDoUpdate({\n target: this.schema.podUsage.podId,\n set: updateSet,\n });\n }\n\n /**\n * Generic account limit setter for compute/token limits.\n */\n private async upsertAccountLimit(client: DbClient, accountId: string, field: 'computeLimitSeconds' | 'tokenLimitMonthly', value: number | null): Promise<void> {\n const insertValues: Record<string, unknown> = {\n accountId,\n storageBytes: 0,\n ingressBytes: 0,\n egressBytes: 0,\n [field]: value,\n };\n await client.insert(this.schema.accountUsage)\n .values(insertValues)\n .onConflictDoUpdate({\n target: this.schema.accountUsage.accountId,\n set: {\n [field]: value,\n updatedAt: this.now(),\n },\n });\n }\n\n /**\n * Generic pod limit setter for compute/token limits.\n */\n private async upsertPodLimit(client: DbClient, accountId: string, podId: string, field: 'computeLimitSeconds' | 'tokenLimitMonthly', value: number | null): Promise<void> {\n const insertValues: Record<string, unknown> = {\n podId,\n accountId,\n storageBytes: 0,\n ingressBytes: 0,\n egressBytes: 0,\n [field]: value,\n };\n await client.insert(this.schema.podUsage)\n .values(insertValues)\n .onConflictDoUpdate({\n target: this.schema.podUsage.podId,\n set: {\n accountId,\n [field]: value,\n updatedAt: this.now(),\n },\n });\n }\n\n private async getPodUsageWith(client: DbClient, podId: string): Promise<PodUsageRecord | undefined> {\n const result = await client.select({\n accountId: this.schema.podUsage.accountId,\n storage: this.schema.podUsage.storageBytes,\n ingress: this.schema.podUsage.ingressBytes,\n egress: this.schema.podUsage.egressBytes,\n storageLimit: this.schema.podUsage.storageLimitBytes,\n bandwidthLimit: this.schema.podUsage.bandwidthLimitBps,\n computeSeconds: this.schema.podUsage.computeSeconds,\n tokensUsed: this.schema.podUsage.tokensUsed,\n computeLimitSeconds: this.schema.podUsage.computeLimitSeconds,\n tokenLimitMonthly: this.schema.podUsage.tokenLimitMonthly,\n periodStart: this.schema.podUsage.periodStart,\n }).from(this.schema.podUsage)\n .where(eq(this.schema.podUsage.podId, podId));\n if (!result || result.length === 0) {\n return undefined;\n }\n const row = result[0];\n const accountId = String(row.accountId);\n return {\n podId,\n accountId,\n storageBytes: this.coerceNumber(row.storage),\n ingressBytes: this.coerceNumber(row.ingress),\n egressBytes: this.coerceNumber(row.egress),\n storageLimitBytes: this.coerceNullable(row.storageLimit),\n bandwidthLimitBps: this.coerceNullable(row.bandwidthLimit),\n computeSeconds: this.coerceNumber(row.computeSeconds),\n tokensUsed: this.coerceNumber(row.tokensUsed),\n computeLimitSeconds: this.coerceNullable(row.computeLimitSeconds),\n tokenLimitMonthly: this.coerceNullable(row.tokenLimitMonthly),\n periodStart: this.coerceTimestamp(row.periodStart),\n };\n }\n\n private normalizeDelta(value: number): number {\n if (!Number.isFinite(value) || value === 0) {\n return 0;\n }\n return Math.trunc(value);\n }\n\n private normalizeValue(value: number): number {\n if (!Number.isFinite(value) || value <= 0) {\n return 0;\n }\n return Math.max(0, Math.trunc(value));\n }\n\n private coerceNumber(value: unknown): number {\n const numeric = Number(value ?? 0);\n return Number.isFinite(numeric) ? numeric : 0;\n }\n\n private coerceNullable(value: unknown): number | null | undefined {\n if (value === undefined) {\n return undefined;\n }\n if (value === null) {\n return null;\n }\n const numeric = Number(value);\n if (!Number.isFinite(numeric)) {\n return null;\n }\n return Math.trunc(numeric);\n }\n\n /**\n * Coerce timestamp value to Unix timestamp (seconds).\n * Handles Date objects (from PG) and numbers (from SQLite).\n */\n private coerceTimestamp(value: unknown): number | null {\n if (value === null || value === undefined) {\n return null;\n }\n if (value instanceof Date) {\n return Math.floor(value.getTime() / 1000);\n }\n if (typeof value === 'number') {\n return value;\n }\n return null;\n }\n\n /**\n * Get the current timestamp in the format expected by the database.\n * PG expects Date objects, SQLite expects Unix timestamps (seconds).\n */\n private now(): Date | number {\n const timestamp = new Date();\n return isDatabaseSqlite(this.db) ? Math.floor(timestamp.getTime() / 1000) : timestamp;\n }\n}\n"]}
|
|
@@ -119,6 +119,15 @@ export declare class ComunicaQuintEngine {
|
|
|
119
119
|
* Uses RDF.Store interface since UPDATE doesn't need FILTER pushdown
|
|
120
120
|
*/
|
|
121
121
|
queryVoid(query: string, context?: QueryContext): Promise<void>;
|
|
122
|
+
/**
|
|
123
|
+
* Parse "DELETE WHERE { GRAPH <uri> { ?s ?p ?o. } }" and return the graph URI.
|
|
124
|
+
* Returns null if the statement doesn't match this pattern.
|
|
125
|
+
*/
|
|
126
|
+
private parseDeleteWhereGraph;
|
|
127
|
+
/**
|
|
128
|
+
* Split a compound SPARQL UPDATE into individual statements.
|
|
129
|
+
*/
|
|
130
|
+
private splitUpdateStatements;
|
|
122
131
|
/**
|
|
123
132
|
* Extract optimization params from SPARQL query
|
|
124
133
|
*/
|
|
@@ -559,25 +559,66 @@ class ComunicaQuintEngine {
|
|
|
559
559
|
* Uses RDF.Store interface since UPDATE doesn't need FILTER pushdown
|
|
560
560
|
*/
|
|
561
561
|
async queryVoid(query, context) {
|
|
562
|
-
console.log(`[ComunicaQuintEngine.queryVoid] Starting: ${query.slice(0, 100)}...`);
|
|
563
562
|
this.currentSecurityFilters = context?.filters;
|
|
564
563
|
try {
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
564
|
+
// Comunica does not properly await the RDF.Store remove() EventEmitter
|
|
565
|
+
// before proceeding to the next operation. This causes DELETE WHERE to
|
|
566
|
+
// complete after INSERT DATA, deleting newly inserted triples.
|
|
567
|
+
// Fix: split compound updates and handle DELETE WHERE directly via QuintStore.
|
|
568
|
+
const statements = this.splitUpdateStatements(query);
|
|
569
|
+
for (const stmt of statements) {
|
|
570
|
+
const deleteGraphUri = this.parseDeleteWhereGraph(stmt);
|
|
571
|
+
if (deleteGraphUri) {
|
|
572
|
+
// Execute DELETE WHERE directly via QuintStore.del()
|
|
573
|
+
await this.store.del({ graph: { termType: 'NamedNode', value: deleteGraphUri } });
|
|
574
|
+
}
|
|
575
|
+
else {
|
|
576
|
+
await this.engine.queryVoid(stmt, {
|
|
577
|
+
sources: [this.rdfStore],
|
|
578
|
+
...context,
|
|
579
|
+
});
|
|
580
|
+
}
|
|
581
|
+
}
|
|
572
582
|
}
|
|
573
583
|
catch (err) {
|
|
574
|
-
console.error(`[ComunicaQuintEngine.queryVoid] Failed:`, err);
|
|
575
584
|
throw err;
|
|
576
585
|
}
|
|
577
586
|
finally {
|
|
578
587
|
this.currentSecurityFilters = undefined;
|
|
579
588
|
}
|
|
580
589
|
}
|
|
590
|
+
/**
|
|
591
|
+
* Parse "DELETE WHERE { GRAPH <uri> { ?s ?p ?o. } }" and return the graph URI.
|
|
592
|
+
* Returns null if the statement doesn't match this pattern.
|
|
593
|
+
*/
|
|
594
|
+
parseDeleteWhereGraph(stmt) {
|
|
595
|
+
const m = stmt.match(/^\s*DELETE\s+WHERE\s*\{\s*GRAPH\s*<([^>]+)>\s*\{\s*\?(\w+)\s+\?(\w+)\s+\?(\w+)\s*\.?\s*\}\s*\}\s*$/i);
|
|
596
|
+
return m ? m[1] : null;
|
|
597
|
+
}
|
|
598
|
+
/**
|
|
599
|
+
* Split a compound SPARQL UPDATE into individual statements.
|
|
600
|
+
*/
|
|
601
|
+
splitUpdateStatements(query) {
|
|
602
|
+
const statements = [];
|
|
603
|
+
let depth = 0;
|
|
604
|
+
let start = 0;
|
|
605
|
+
for (let i = 0; i < query.length; i++) {
|
|
606
|
+
if (query[i] === '{')
|
|
607
|
+
depth++;
|
|
608
|
+
else if (query[i] === '}')
|
|
609
|
+
depth--;
|
|
610
|
+
else if (query[i] === ';' && depth === 0) {
|
|
611
|
+
const stmt = query.slice(start, i).trim();
|
|
612
|
+
if (stmt)
|
|
613
|
+
statements.push(stmt);
|
|
614
|
+
start = i + 1;
|
|
615
|
+
}
|
|
616
|
+
}
|
|
617
|
+
const last = query.slice(start).trim();
|
|
618
|
+
if (last)
|
|
619
|
+
statements.push(last);
|
|
620
|
+
return statements;
|
|
621
|
+
}
|
|
581
622
|
/**
|
|
582
623
|
* Extract optimization params from SPARQL query
|
|
583
624
|
*/
|