target-supabase-sdk 0.2.15 → 0.2.16
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/browser.d.ts +4 -2
- package/dist/browser.d.ts.map +1 -1
- package/dist/browser.js +1 -1
- package/dist/chunks/{task-queue-DCY_0Qj0.js → task-queue-Gi4DSq74.js} +135 -121
- package/dist/chunks/task-queue-Gi4DSq74.js.map +1 -0
- package/dist/config/config.api.d.ts +61 -0
- package/dist/config/config.api.d.ts.map +1 -0
- package/dist/{service → config}/config.interface.d.ts +1 -3
- package/dist/config/config.interface.d.ts.map +1 -0
- package/dist/config/index.d.ts +9 -0
- package/dist/config/index.d.ts.map +1 -0
- package/dist/node/runtime-state/service-runtime-state.types.d.ts +1 -1
- package/dist/node/runtime-state/service-runtime-state.types.d.ts.map +1 -1
- package/dist/node/service-guard/registry-slot-guard-step.d.ts +1 -1
- package/dist/node/service-guard/registry-slot-guard-step.d.ts.map +1 -1
- package/dist/node/service-guard/service-guard.interface.d.ts +1 -1
- package/dist/node/service-guard/service-guard.interface.d.ts.map +1 -1
- package/dist/node/service-host/claim-registry-slot.d.ts +1 -1
- package/dist/node/service-host/claim-registry-slot.d.ts.map +1 -1
- package/dist/node/service-host/service-host.d.ts +1 -1
- package/dist/node/service-host/service-host.d.ts.map +1 -1
- package/dist/node/service-host/single-process-service.d.ts +1 -1
- package/dist/node/service-host/single-process-service.d.ts.map +1 -1
- package/dist/node.js +2 -2
- package/dist/node.js.map +1 -1
- package/dist/service/index.d.ts +5 -10
- package/dist/service/index.d.ts.map +1 -1
- package/dist/service/registry/index.d.ts +14 -0
- package/dist/service/registry/index.d.ts.map +1 -0
- package/dist/service/{registry-lifecycle.d.ts → registry/registry-lifecycle.d.ts} +1 -1
- package/dist/service/registry/registry-lifecycle.d.ts.map +1 -0
- package/dist/service/{config.api.d.ts → registry/registry.api.d.ts} +5 -65
- package/dist/service/registry/registry.api.d.ts.map +1 -0
- package/dist/service/registry/registry.constant.d.ts +23 -0
- package/dist/service/registry/registry.constant.d.ts.map +1 -0
- package/dist/service/registry/registry.interface.d.ts +15 -0
- package/dist/service/registry/registry.interface.d.ts.map +1 -0
- package/dist/service/{registry.service.d.ts → registry/registry.service.d.ts} +23 -15
- package/dist/service/registry/registry.service.d.ts.map +1 -0
- package/dist/service/service.interface.d.ts +0 -10
- package/dist/service/service.interface.d.ts.map +1 -1
- package/package.json +1 -1
- package/src/browser.ts +10 -9
- package/src/config/config.api.ts +72 -0
- package/src/{service → config}/config.interface.ts +1 -4
- package/src/config/index.ts +9 -0
- package/src/node/runtime-state/create-service-runtime-state-store.ts +1 -1
- package/src/node/runtime-state/service-runtime-state.types.ts +1 -1
- package/src/node/service-guard/registry-slot-guard-step.ts +4 -1
- package/src/node/service-guard/run-service-guard-tick.ts +1 -1
- package/src/node/service-guard/service-guard.interface.ts +1 -1
- package/src/node/service-host/claim-registry-slot.ts +2 -2
- package/src/node/service-host/service-host.ts +2 -2
- package/src/node/service-host/single-process-service.ts +1 -1
- package/src/service/index.ts +30 -40
- package/src/service/registry/index.ts +65 -0
- package/src/service/{registry-lifecycle.ts → registry/registry-lifecycle.ts} +3 -3
- package/src/service/{config.api.ts → registry/registry.api.ts} +6 -80
- package/src/service/registry/registry.constant.ts +17 -0
- package/src/service/registry/registry.interface.ts +16 -0
- package/src/service/{registry.service.ts → registry/registry.service.ts} +66 -65
- package/src/service/service.interface.ts +0 -12
- package/dist/chunks/task-queue-DCY_0Qj0.js.map +0 -1
- package/dist/service/config.api.d.ts.map +0 -1
- package/dist/service/config.interface.d.ts.map +0 -1
- package/dist/service/registry-lifecycle.d.ts.map +0 -1
- package/dist/service/registry.service.d.ts.map +0 -1
package/src/service/index.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Service domain public API — curated re-exports only.
|
|
3
|
+
* System registry: `./registry/` (seed, claim, slot views).
|
|
3
4
|
*/
|
|
4
5
|
|
|
5
6
|
export type {
|
|
@@ -10,68 +11,58 @@ export type {
|
|
|
10
11
|
} from "./base.interface";
|
|
11
12
|
export { ServiceLifecycleStatus } from "./base.interface";
|
|
12
13
|
export type {
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
SystemRegistrySeedSlot,
|
|
17
|
-
} from "./config.api";
|
|
18
|
-
export {
|
|
19
|
-
buildEmptyServiceSlots,
|
|
20
|
-
buildSystemRegistryConfigDetails,
|
|
21
|
-
DEFAULT_SYSTEM_REGISTRY_SEED_SLOTS,
|
|
22
|
-
getConfig,
|
|
23
|
-
getConfigSchema,
|
|
24
|
-
postSystemRegistryConfig,
|
|
25
|
-
postSystemRegistryConfigSchema,
|
|
26
|
-
resetSystemRegistryConfig,
|
|
27
|
-
resetSystemRegistryConfigSchema,
|
|
28
|
-
systemRegistrySeedSlotSchema,
|
|
29
|
-
} from "./config.api";
|
|
30
|
-
export type { Config, ConfigDetails } from "./config.interface";
|
|
31
|
-
export { CategoryConfig, TARGET_SYSTEM_REGISTRY_KEY } from "./config.interface";
|
|
32
|
-
export type {
|
|
33
|
-
AppendSystemRegistrySlotsInput,
|
|
34
|
-
AppendSystemRegistrySlotsOutcome,
|
|
14
|
+
AppendSystemRegistryEmptySlotsInput,
|
|
15
|
+
AppendSystemRegistryEmptySlotsOutcome,
|
|
16
|
+
ClaimRegistrySlotInput,
|
|
35
17
|
PatchServiceRuntimeInput,
|
|
18
|
+
PostSystemRegistryConfigPayload,
|
|
36
19
|
RegisterServiceInput,
|
|
20
|
+
RegistrySlotGuardResult,
|
|
21
|
+
RegistrySlotRuntimeState,
|
|
37
22
|
ReleasedRegistrySlot,
|
|
38
23
|
ReleaseSystemRegistrySlotsByServiceIdInput,
|
|
39
24
|
ReleaseSystemRegistrySlotsByServiceIdOutcome,
|
|
40
25
|
ReleaseSystemRegistrySlotsInput,
|
|
41
26
|
ReleaseSystemRegistrySlotsOutcome,
|
|
27
|
+
ResetSystemRegistryConfigPayload,
|
|
28
|
+
ServiceRegistrySession,
|
|
29
|
+
ServiceSlot,
|
|
30
|
+
SystemRegistrySeedSlot,
|
|
42
31
|
TargetSystemRegistrySlotView,
|
|
43
32
|
TargetSystemRegistryView,
|
|
44
|
-
} from "./registry
|
|
33
|
+
} from "./registry/index";
|
|
45
34
|
export {
|
|
46
|
-
|
|
35
|
+
appendSystemRegistryEmptySlots,
|
|
47
36
|
assertRegistrySlotAvailable,
|
|
48
37
|
assertRegistrySlotOwner,
|
|
38
|
+
buildEmptyServiceSlots,
|
|
39
|
+
buildSystemRegistryConfigDetails,
|
|
40
|
+
claimServiceRegistrySlot,
|
|
41
|
+
createClaimedRegistrySlotRuntimeState,
|
|
42
|
+
DEFAULT_SYSTEM_REGISTRY_SEED_SLOTS,
|
|
43
|
+
EMPTY_REGISTRY_SLOT_RUNTIME_STATE,
|
|
49
44
|
getTargetSystemRegistry,
|
|
50
45
|
parseServiceSlot,
|
|
51
46
|
parseServiceSlots,
|
|
52
47
|
patchServiceRuntime,
|
|
48
|
+
postSystemRegistryConfig,
|
|
49
|
+
postSystemRegistryConfigSchema,
|
|
53
50
|
registerService,
|
|
54
51
|
registerServiceAtStartup,
|
|
52
|
+
registrySlotRuntimePatchFromGuardResult,
|
|
55
53
|
releaseSystemRegistrySlots,
|
|
56
54
|
releaseSystemRegistrySlotsByServiceId,
|
|
55
|
+
resetSystemRegistryConfig,
|
|
56
|
+
resetSystemRegistryConfigSchema,
|
|
57
57
|
resolveActiveRegistryServiceId,
|
|
58
|
+
runRegistrySlotGuardCheck,
|
|
58
59
|
ServiceRegistryError,
|
|
60
|
+
ServiceSlotStatus,
|
|
61
|
+
systemRegistrySeedSlotSchema,
|
|
62
|
+
TARGET_SYSTEM_REGISTRY_KEY,
|
|
59
63
|
unregisterService,
|
|
60
64
|
unregisterServiceAtShutdown,
|
|
61
|
-
} from "./registry
|
|
62
|
-
export type {
|
|
63
|
-
ClaimRegistrySlotInput,
|
|
64
|
-
RegistrySlotGuardResult,
|
|
65
|
-
RegistrySlotRuntimeState,
|
|
66
|
-
ServiceRegistrySession,
|
|
67
|
-
} from "./registry-lifecycle";
|
|
68
|
-
export {
|
|
69
|
-
claimServiceRegistrySlot,
|
|
70
|
-
createClaimedRegistrySlotRuntimeState,
|
|
71
|
-
EMPTY_REGISTRY_SLOT_RUNTIME_STATE,
|
|
72
|
-
registrySlotRuntimePatchFromGuardResult,
|
|
73
|
-
runRegistrySlotGuardCheck,
|
|
74
|
-
} from "./registry-lifecycle";
|
|
65
|
+
} from "./registry/index";
|
|
75
66
|
export type { GetApiPayload, GetServicePayload, PostApiPayload, PostServicePayload } from "./service.api";
|
|
76
67
|
export {
|
|
77
68
|
apiDetailsSchema,
|
|
@@ -97,9 +88,8 @@ export type {
|
|
|
97
88
|
ServiceDetails,
|
|
98
89
|
ServiceNodeSnapshot,
|
|
99
90
|
ServiceRuntime,
|
|
100
|
-
ServiceSlot,
|
|
101
91
|
} from "./service.interface";
|
|
102
|
-
export { ApiMethod, CategoryApi, CategoryService
|
|
92
|
+
export { ApiMethod, CategoryApi, CategoryService } from "./service.interface";
|
|
103
93
|
export type { PostServiceInstanceOptions, ServiceBootstrapResult } from "./service-bootstrap";
|
|
104
94
|
export {
|
|
105
95
|
createActiveServiceLifecycle,
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* System service registry — curated re-exports only.
|
|
3
|
+
* Generic Config CRUD lives in `src/config/`.
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
export type {
|
|
7
|
+
PostSystemRegistryConfigPayload,
|
|
8
|
+
ResetSystemRegistryConfigPayload,
|
|
9
|
+
SystemRegistrySeedSlot,
|
|
10
|
+
} from "./registry.api";
|
|
11
|
+
export {
|
|
12
|
+
buildEmptyServiceSlots,
|
|
13
|
+
buildSystemRegistryConfigDetails,
|
|
14
|
+
postSystemRegistryConfig,
|
|
15
|
+
postSystemRegistryConfigSchema,
|
|
16
|
+
resetSystemRegistryConfig,
|
|
17
|
+
resetSystemRegistryConfigSchema,
|
|
18
|
+
systemRegistrySeedSlotSchema,
|
|
19
|
+
} from "./registry.api";
|
|
20
|
+
export { DEFAULT_SYSTEM_REGISTRY_SEED_SLOTS, TARGET_SYSTEM_REGISTRY_KEY } from "./registry.constant";
|
|
21
|
+
export type { ServiceSlot } from "./registry.interface";
|
|
22
|
+
export { ServiceSlotStatus } from "./registry.interface";
|
|
23
|
+
export type {
|
|
24
|
+
AppendSystemRegistryEmptySlotsInput,
|
|
25
|
+
AppendSystemRegistryEmptySlotsOutcome,
|
|
26
|
+
PatchServiceRuntimeInput,
|
|
27
|
+
RegisterServiceInput,
|
|
28
|
+
ReleasedRegistrySlot,
|
|
29
|
+
ReleaseSystemRegistrySlotsByServiceIdInput,
|
|
30
|
+
ReleaseSystemRegistrySlotsByServiceIdOutcome,
|
|
31
|
+
ReleaseSystemRegistrySlotsInput,
|
|
32
|
+
ReleaseSystemRegistrySlotsOutcome,
|
|
33
|
+
TargetSystemRegistrySlotView,
|
|
34
|
+
TargetSystemRegistryView,
|
|
35
|
+
} from "./registry.service";
|
|
36
|
+
export {
|
|
37
|
+
appendSystemRegistryEmptySlots,
|
|
38
|
+
assertRegistrySlotAvailable,
|
|
39
|
+
assertRegistrySlotOwner,
|
|
40
|
+
getTargetSystemRegistry,
|
|
41
|
+
parseServiceSlot,
|
|
42
|
+
parseServiceSlots,
|
|
43
|
+
patchServiceRuntime,
|
|
44
|
+
registerService,
|
|
45
|
+
registerServiceAtStartup,
|
|
46
|
+
releaseSystemRegistrySlots,
|
|
47
|
+
releaseSystemRegistrySlotsByServiceId,
|
|
48
|
+
resolveActiveRegistryServiceId,
|
|
49
|
+
ServiceRegistryError,
|
|
50
|
+
unregisterService,
|
|
51
|
+
unregisterServiceAtShutdown,
|
|
52
|
+
} from "./registry.service";
|
|
53
|
+
export type {
|
|
54
|
+
ClaimRegistrySlotInput,
|
|
55
|
+
RegistrySlotGuardResult,
|
|
56
|
+
RegistrySlotRuntimeState,
|
|
57
|
+
ServiceRegistrySession,
|
|
58
|
+
} from "./registry-lifecycle";
|
|
59
|
+
export {
|
|
60
|
+
claimServiceRegistrySlot,
|
|
61
|
+
createClaimedRegistrySlotRuntimeState,
|
|
62
|
+
EMPTY_REGISTRY_SLOT_RUNTIME_STATE,
|
|
63
|
+
registrySlotRuntimePatchFromGuardResult,
|
|
64
|
+
runRegistrySlotGuardCheck,
|
|
65
|
+
} from "./registry-lifecycle";
|
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
import { deleteTarget } from "
|
|
2
|
-
import { createLogger } from "
|
|
1
|
+
import { deleteTarget } from "../../core.api";
|
|
2
|
+
import { createLogger } from "../../shared/log";
|
|
3
|
+
import type { Service } from "../service.interface";
|
|
3
4
|
import {
|
|
4
5
|
assertRegistrySlotAvailable,
|
|
5
6
|
assertRegistrySlotOwner,
|
|
@@ -7,7 +8,6 @@ import {
|
|
|
7
8
|
ServiceRegistryError,
|
|
8
9
|
unregisterServiceAtShutdown,
|
|
9
10
|
} from "./registry.service";
|
|
10
|
-
import type { Service } from "./service.interface";
|
|
11
11
|
|
|
12
12
|
const LOG_TOPIC = "service-registry-lifecycle";
|
|
13
13
|
|
|
@@ -1,34 +1,16 @@
|
|
|
1
1
|
import { z } from "zod";
|
|
2
|
+
import { getConfig } from "../../config/config.api";
|
|
3
|
+
import { CategoryConfig, type Config, type ConfigDetails } from "../../config/config.interface";
|
|
2
4
|
import {
|
|
3
5
|
createTarget,
|
|
4
|
-
getPossibleTarget,
|
|
5
|
-
getTarget,
|
|
6
6
|
isOptimisticLockError,
|
|
7
7
|
type QueryFilter,
|
|
8
8
|
updateTargetDetails,
|
|
9
9
|
validateWithSchema,
|
|
10
|
-
} from "
|
|
11
|
-
import { generateResponse } from "
|
|
12
|
-
import {
|
|
13
|
-
import { type ServiceSlot, ServiceSlotStatus } from "./
|
|
14
|
-
|
|
15
|
-
const targetIdSchema = z.string().trim().min(1);
|
|
16
|
-
|
|
17
|
-
export const getConfigSchema = z
|
|
18
|
-
.object({
|
|
19
|
-
id: targetIdSchema.optional(),
|
|
20
|
-
value: z.string().trim().min(1).optional(),
|
|
21
|
-
})
|
|
22
|
-
.refine(
|
|
23
|
-
(payload) => {
|
|
24
|
-
const hasId = payload.id != null && payload.id !== "";
|
|
25
|
-
const hasValue = payload.value != null && payload.value !== "";
|
|
26
|
-
return hasId !== hasValue;
|
|
27
|
-
},
|
|
28
|
-
{ message: "Provide exactly one of id or value" },
|
|
29
|
-
);
|
|
30
|
-
|
|
31
|
-
export type GetConfigPayload = z.infer<typeof getConfigSchema>;
|
|
10
|
+
} from "../../core.api";
|
|
11
|
+
import { generateResponse } from "../../core.interface";
|
|
12
|
+
import { DEFAULT_SYSTEM_REGISTRY_SEED_SLOTS, TARGET_SYSTEM_REGISTRY_KEY } from "./registry.constant";
|
|
13
|
+
import { type ServiceSlot, ServiceSlotStatus } from "./registry.interface";
|
|
32
14
|
|
|
33
15
|
/** One declarative EMPTY slot entry for seeding the system registry. */
|
|
34
16
|
export const systemRegistrySeedSlotSchema = z.object({
|
|
@@ -53,33 +35,12 @@ export type ResetSystemRegistryConfigPayload = PostSystemRegistryConfigPayload;
|
|
|
53
35
|
const DEFAULT_RESET_RETRY_ATTEMPTS = 5;
|
|
54
36
|
const RESET_RETRY_DELAY_MS = 50;
|
|
55
37
|
|
|
56
|
-
/** Default one EMPTY slot per known L3 service (override via payload or seed file). */
|
|
57
|
-
export const DEFAULT_SYSTEM_REGISTRY_SEED_SLOTS: readonly SystemRegistrySeedSlot[] = [
|
|
58
|
-
{ serviceValue: "log-service" },
|
|
59
|
-
{ serviceValue: "watch-service" },
|
|
60
|
-
{ serviceValue: "download-service" },
|
|
61
|
-
{ serviceValue: "storage-service" },
|
|
62
|
-
{ serviceValue: "gc-service" },
|
|
63
|
-
{ serviceValue: "upload-service" },
|
|
64
|
-
{ serviceValue: "cv-service" },
|
|
65
|
-
] as const;
|
|
66
|
-
|
|
67
38
|
const configCategoryFilter: QueryFilter = {
|
|
68
39
|
field: "category",
|
|
69
40
|
operator: "eq",
|
|
70
41
|
value: CategoryConfig.CONFIG,
|
|
71
42
|
};
|
|
72
43
|
|
|
73
|
-
function buildConfigLookupFilters(payload: GetConfigPayload): QueryFilter[] {
|
|
74
|
-
const filters: QueryFilter[] = [configCategoryFilter];
|
|
75
|
-
|
|
76
|
-
if (payload.id == null || payload.id === "") {
|
|
77
|
-
filters.push({ field: "value", operator: "eq", value: payload.value! });
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
return filters;
|
|
81
|
-
}
|
|
82
|
-
|
|
83
44
|
/** Build EMPTY {@link ServiceSlot} rows from seed entries (one slot per array item). */
|
|
84
45
|
export function buildEmptyServiceSlots(seedSlots: readonly SystemRegistrySeedSlot[]): ServiceSlot[] {
|
|
85
46
|
return seedSlots.map(({ serviceValue }) => ({
|
|
@@ -113,41 +74,6 @@ export function buildSystemRegistryConfigDetails(slots: readonly ServiceSlot[]):
|
|
|
113
74
|
};
|
|
114
75
|
}
|
|
115
76
|
|
|
116
|
-
/** Fetch a Config by id or by {@link Config.value} key (`category=config`). */
|
|
117
|
-
export const getConfig = validateWithSchema(
|
|
118
|
-
getConfigSchema,
|
|
119
|
-
"getConfigSchema",
|
|
120
|
-
)(async (payload) => {
|
|
121
|
-
const filterList = buildConfigLookupFilters(payload);
|
|
122
|
-
|
|
123
|
-
if (payload.id != null && payload.id !== "") {
|
|
124
|
-
const result = await getTarget({
|
|
125
|
-
id: payload.id,
|
|
126
|
-
filterList,
|
|
127
|
-
});
|
|
128
|
-
return {
|
|
129
|
-
...result,
|
|
130
|
-
data: result.data as Config,
|
|
131
|
-
};
|
|
132
|
-
}
|
|
133
|
-
|
|
134
|
-
const result = await getPossibleTarget({
|
|
135
|
-
filterList,
|
|
136
|
-
});
|
|
137
|
-
|
|
138
|
-
if (result.data == null) {
|
|
139
|
-
return {
|
|
140
|
-
...result,
|
|
141
|
-
data: undefined,
|
|
142
|
-
};
|
|
143
|
-
}
|
|
144
|
-
|
|
145
|
-
return {
|
|
146
|
-
...result,
|
|
147
|
-
data: result.data as Config,
|
|
148
|
-
};
|
|
149
|
-
});
|
|
150
|
-
|
|
151
77
|
/**
|
|
152
78
|
* Insert the globally unique system registry Config (`category=config`,
|
|
153
79
|
* `value=target-system-registry`). Rejects duplicates via `checkRedundancyFilterList`.
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/** Globally unique Config key for the declarative system service registry. */
|
|
2
|
+
export const TARGET_SYSTEM_REGISTRY_KEY = "target-system-registry";
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Default one EMPTY slot per known L3 service.
|
|
6
|
+
* Override via `postSystemRegistryConfig` / `resetSystemRegistryConfig` payload or gc-service seed file.
|
|
7
|
+
* Replica count = how many times the same `serviceValue` appears (not a separate maxInstances field).
|
|
8
|
+
*/
|
|
9
|
+
export const DEFAULT_SYSTEM_REGISTRY_SEED_SLOTS = [
|
|
10
|
+
{ serviceValue: "log-service" },
|
|
11
|
+
{ serviceValue: "watch-service" },
|
|
12
|
+
{ serviceValue: "download-service" },
|
|
13
|
+
{ serviceValue: "storage-service" },
|
|
14
|
+
{ serviceValue: "gc-service" },
|
|
15
|
+
{ serviceValue: "upload-service" },
|
|
16
|
+
{ serviceValue: "cv-service" },
|
|
17
|
+
] as const;
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Capacity slots on the system registry Config (`details.objects`).
|
|
3
|
+
* Not fields on a Service Target row — see {@link Service} in `service.interface.ts`.
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
export enum ServiceSlotStatus {
|
|
7
|
+
EMPTY = "EMPTY",
|
|
8
|
+
ACTIVE = "ACTIVE",
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export interface ServiceSlot {
|
|
12
|
+
serviceValue: string;
|
|
13
|
+
/** Bound Service.id when {@link ServiceSlotStatus.ACTIVE}; null when EMPTY. */
|
|
14
|
+
serviceId: string | null;
|
|
15
|
+
status: ServiceSlotStatus;
|
|
16
|
+
}
|
|
@@ -9,21 +9,17 @@
|
|
|
9
9
|
* for crashed / ungraceful exits (stale `Service.details.runtime`)
|
|
10
10
|
*/
|
|
11
11
|
|
|
12
|
-
import {
|
|
13
|
-
import type {
|
|
14
|
-
import {
|
|
15
|
-
import {
|
|
16
|
-
import {
|
|
17
|
-
import { getService } from "
|
|
18
|
-
import {
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
ServiceSlotStatus,
|
|
24
|
-
} from "./service.interface";
|
|
25
|
-
|
|
26
|
-
export { TARGET_SYSTEM_REGISTRY_KEY } from "./config.interface";
|
|
12
|
+
import { getConfig } from "../../config/config.api";
|
|
13
|
+
import type { Config, ConfigDetails } from "../../config/config.interface";
|
|
14
|
+
import { isOptimisticLockError, updateTargetDetails } from "../../core.api";
|
|
15
|
+
import type { Node } from "../../node/node.interface";
|
|
16
|
+
import { createLogger } from "../../shared/log";
|
|
17
|
+
import { getService } from "../service.api";
|
|
18
|
+
import type { Service, ServiceDetails, ServiceNodeSnapshot } from "../service.interface";
|
|
19
|
+
import { TARGET_SYSTEM_REGISTRY_KEY } from "./registry.constant";
|
|
20
|
+
import { type ServiceSlot, ServiceSlotStatus } from "./registry.interface";
|
|
21
|
+
|
|
22
|
+
export { TARGET_SYSTEM_REGISTRY_KEY } from "./registry.constant";
|
|
27
23
|
|
|
28
24
|
/** `details.meta.revision` on the system registry Config — optimistic-lock token. */
|
|
29
25
|
interface RegistryConfigMeta {
|
|
@@ -85,19 +81,24 @@ export interface ReleaseSystemRegistrySlotsByServiceIdOutcome {
|
|
|
85
81
|
unchangedServiceIds: string[];
|
|
86
82
|
}
|
|
87
83
|
|
|
88
|
-
export interface
|
|
89
|
-
/** Logical service
|
|
90
|
-
|
|
84
|
+
export interface AppendSystemRegistryEmptySlotsInput {
|
|
85
|
+
/** Logical service key (e.g. `download-service`). */
|
|
86
|
+
serviceValue: string;
|
|
87
|
+
/** How many EMPTY slots to append. Default `1`. */
|
|
88
|
+
count?: number;
|
|
91
89
|
traceId?: string;
|
|
92
90
|
maxAttempts?: number;
|
|
93
91
|
}
|
|
94
92
|
|
|
95
|
-
export interface
|
|
93
|
+
export interface AppendSystemRegistryEmptySlotsOutcome {
|
|
96
94
|
config: Config;
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
95
|
+
serviceValue: string;
|
|
96
|
+
/** EMPTY slots appended this run. */
|
|
97
|
+
appended: number;
|
|
98
|
+
/** Declared slot count for `serviceValue` before this run. */
|
|
99
|
+
capacityBefore: number;
|
|
100
|
+
/** Declared slot count for `serviceValue` after this run. */
|
|
101
|
+
capacityAfter: number;
|
|
101
102
|
}
|
|
102
103
|
|
|
103
104
|
export class ServiceRegistryError extends Error {
|
|
@@ -618,30 +619,35 @@ export async function releaseSystemRegistrySlotsByServiceId(
|
|
|
618
619
|
}
|
|
619
620
|
|
|
620
621
|
/**
|
|
621
|
-
* Append EMPTY {@link ServiceSlot} rows for
|
|
622
|
-
*
|
|
622
|
+
* Append one or more EMPTY {@link ServiceSlot} rows for a given `serviceValue`.
|
|
623
|
+
*
|
|
624
|
+
* Always grows capacity (does not skip when the key is already declared).
|
|
625
|
+
* Use for replica scale-out (e.g. second `download-service` instance).
|
|
623
626
|
* Does not modify existing slots or release ACTIVE bindings.
|
|
624
627
|
*/
|
|
625
|
-
export async function
|
|
626
|
-
input:
|
|
627
|
-
): Promise<
|
|
628
|
-
const
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
628
|
+
export async function appendSystemRegistryEmptySlots(
|
|
629
|
+
input: AppendSystemRegistryEmptySlotsInput,
|
|
630
|
+
): Promise<AppendSystemRegistryEmptySlotsOutcome> {
|
|
631
|
+
const serviceValue = input.serviceValue.trim();
|
|
632
|
+
if (serviceValue === "") {
|
|
633
|
+
throw new Error("[appendSystemRegistryEmptySlots] serviceValue must not be empty");
|
|
634
|
+
}
|
|
635
|
+
|
|
636
|
+
const count = input.count ?? 1;
|
|
637
|
+
if (!Number.isInteger(count) || count < 1) {
|
|
638
|
+
throw new Error("[appendSystemRegistryEmptySlots] count must be an integer >= 1");
|
|
633
639
|
}
|
|
634
640
|
|
|
635
641
|
const maxAttempts = input.maxAttempts ?? DEFAULT_REGISTER_RETRY_ATTEMPTS;
|
|
636
642
|
const logger = createLogger({
|
|
637
|
-
module: "
|
|
643
|
+
module: "appendSystemRegistryEmptySlots",
|
|
638
644
|
traceId: input.traceId,
|
|
639
|
-
labels: {
|
|
645
|
+
labels: { serviceValue, count: String(count) },
|
|
640
646
|
});
|
|
641
647
|
|
|
642
|
-
logger.info("开始追加 registry
|
|
648
|
+
logger.info("开始追加 EMPTY registry 槽位", {
|
|
643
649
|
topic: LOG_TOPIC_REGISTRY,
|
|
644
|
-
data: {
|
|
650
|
+
data: { serviceValue, count },
|
|
645
651
|
});
|
|
646
652
|
|
|
647
653
|
for (let attempt = 1; attempt <= maxAttempts; attempt += 1) {
|
|
@@ -649,31 +655,16 @@ export async function appendSystemRegistrySlots(
|
|
|
649
655
|
const config = await loadSystemRegistryConfig();
|
|
650
656
|
const revision = parseRegistryRevision(config.details.meta);
|
|
651
657
|
const slots = parseServiceSlots(config);
|
|
658
|
+
const capacityBefore = slots.filter((slot) => slot.serviceValue === serviceValue).length;
|
|
652
659
|
|
|
653
|
-
const
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
for (const serviceValue of serviceValues) {
|
|
658
|
-
if (isServiceValueDeclared(nextSlots, serviceValue)) {
|
|
659
|
-
skipped.push(serviceValue);
|
|
660
|
-
continue;
|
|
661
|
-
}
|
|
662
|
-
nextSlots.push({
|
|
660
|
+
const nextSlots = [
|
|
661
|
+
...slots,
|
|
662
|
+
...Array.from({ length: count }, () => ({
|
|
663
663
|
serviceValue,
|
|
664
664
|
serviceId: null,
|
|
665
665
|
status: ServiceSlotStatus.EMPTY,
|
|
666
|
-
})
|
|
667
|
-
|
|
668
|
-
}
|
|
669
|
-
|
|
670
|
-
if (added.length === 0) {
|
|
671
|
-
logger.info("所有 service 已声明 — 无需追加", {
|
|
672
|
-
topic: LOG_TOPIC_REGISTRY,
|
|
673
|
-
data: { serviceValues, skipped },
|
|
674
|
-
});
|
|
675
|
-
return { config, added, skipped: serviceValues };
|
|
676
|
-
}
|
|
666
|
+
})),
|
|
667
|
+
];
|
|
677
668
|
|
|
678
669
|
await persistSlotClaim({
|
|
679
670
|
configId: config.id,
|
|
@@ -682,33 +673,43 @@ export async function appendSystemRegistrySlots(
|
|
|
682
673
|
});
|
|
683
674
|
|
|
684
675
|
const updated = await loadSystemRegistryConfig();
|
|
685
|
-
|
|
676
|
+
const capacityAfter = parseServiceSlots(updated).filter(
|
|
677
|
+
(slot) => slot.serviceValue === serviceValue,
|
|
678
|
+
).length;
|
|
679
|
+
|
|
680
|
+
logger.info("EMPTY registry 槽位追加成功", {
|
|
686
681
|
topic: LOG_TOPIC_REGISTRY,
|
|
687
|
-
data: {
|
|
682
|
+
data: { serviceValue, appended: count, capacityBefore, capacityAfter, attempt },
|
|
688
683
|
});
|
|
689
684
|
|
|
690
|
-
return {
|
|
685
|
+
return {
|
|
686
|
+
config: updated,
|
|
687
|
+
serviceValue,
|
|
688
|
+
appended: count,
|
|
689
|
+
capacityBefore,
|
|
690
|
+
capacityAfter,
|
|
691
|
+
};
|
|
691
692
|
} catch (error) {
|
|
692
693
|
if (isOptimisticLockError(error) && attempt < maxAttempts) {
|
|
693
694
|
logger.warn("registry 乐观锁冲突,重试", {
|
|
694
695
|
topic: LOG_TOPIC_REGISTRY,
|
|
695
|
-
data: {
|
|
696
|
+
data: { serviceValue, count, attempt, maxAttempts },
|
|
696
697
|
});
|
|
697
698
|
await sleep(50 * attempt);
|
|
698
699
|
continue;
|
|
699
700
|
}
|
|
700
701
|
|
|
701
702
|
const message = error instanceof Error ? error.message : String(error);
|
|
702
|
-
logger.error("registry 槽位追加失败", {
|
|
703
|
+
logger.error("EMPTY registry 槽位追加失败", {
|
|
703
704
|
topic: LOG_TOPIC_REGISTRY,
|
|
704
|
-
data: {
|
|
705
|
+
data: { serviceValue, count, attempt, message },
|
|
705
706
|
});
|
|
706
707
|
throw new ServiceRegistryError(message, "REGISTRY_UPDATE_FAILED");
|
|
707
708
|
}
|
|
708
709
|
}
|
|
709
710
|
|
|
710
711
|
throw new ServiceRegistryError(
|
|
711
|
-
"[
|
|
712
|
+
"[appendSystemRegistryEmptySlots] Optimistic lock retries exhausted",
|
|
712
713
|
"REGISTRY_UPDATE_FAILED",
|
|
713
714
|
);
|
|
714
715
|
}
|
|
@@ -45,18 +45,6 @@ export interface ServiceRuntime {
|
|
|
45
45
|
nodes: ServiceNodeSnapshot[];
|
|
46
46
|
}
|
|
47
47
|
|
|
48
|
-
export enum ServiceSlotStatus {
|
|
49
|
-
EMPTY = "EMPTY",
|
|
50
|
-
ACTIVE = "ACTIVE",
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
export interface ServiceSlot {
|
|
54
|
-
serviceValue: string;
|
|
55
|
-
/** Bound {@link Service.id} when {@link ServiceSlotStatus.ACTIVE}; null when EMPTY. */
|
|
56
|
-
serviceId: string | null;
|
|
57
|
-
status: ServiceSlotStatus;
|
|
58
|
-
}
|
|
59
|
-
|
|
60
48
|
export interface Api extends Target {
|
|
61
49
|
/** "core.post.target.0" 唯一键 领域 + METHOD + content + VERSION */
|
|
62
50
|
value: string;
|