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.
Files changed (67) hide show
  1. package/dist/browser.d.ts +4 -2
  2. package/dist/browser.d.ts.map +1 -1
  3. package/dist/browser.js +1 -1
  4. package/dist/chunks/{task-queue-DCY_0Qj0.js → task-queue-Gi4DSq74.js} +135 -121
  5. package/dist/chunks/task-queue-Gi4DSq74.js.map +1 -0
  6. package/dist/config/config.api.d.ts +61 -0
  7. package/dist/config/config.api.d.ts.map +1 -0
  8. package/dist/{service → config}/config.interface.d.ts +1 -3
  9. package/dist/config/config.interface.d.ts.map +1 -0
  10. package/dist/config/index.d.ts +9 -0
  11. package/dist/config/index.d.ts.map +1 -0
  12. package/dist/node/runtime-state/service-runtime-state.types.d.ts +1 -1
  13. package/dist/node/runtime-state/service-runtime-state.types.d.ts.map +1 -1
  14. package/dist/node/service-guard/registry-slot-guard-step.d.ts +1 -1
  15. package/dist/node/service-guard/registry-slot-guard-step.d.ts.map +1 -1
  16. package/dist/node/service-guard/service-guard.interface.d.ts +1 -1
  17. package/dist/node/service-guard/service-guard.interface.d.ts.map +1 -1
  18. package/dist/node/service-host/claim-registry-slot.d.ts +1 -1
  19. package/dist/node/service-host/claim-registry-slot.d.ts.map +1 -1
  20. package/dist/node/service-host/service-host.d.ts +1 -1
  21. package/dist/node/service-host/service-host.d.ts.map +1 -1
  22. package/dist/node/service-host/single-process-service.d.ts +1 -1
  23. package/dist/node/service-host/single-process-service.d.ts.map +1 -1
  24. package/dist/node.js +2 -2
  25. package/dist/node.js.map +1 -1
  26. package/dist/service/index.d.ts +5 -10
  27. package/dist/service/index.d.ts.map +1 -1
  28. package/dist/service/registry/index.d.ts +14 -0
  29. package/dist/service/registry/index.d.ts.map +1 -0
  30. package/dist/service/{registry-lifecycle.d.ts → registry/registry-lifecycle.d.ts} +1 -1
  31. package/dist/service/registry/registry-lifecycle.d.ts.map +1 -0
  32. package/dist/service/{config.api.d.ts → registry/registry.api.d.ts} +5 -65
  33. package/dist/service/registry/registry.api.d.ts.map +1 -0
  34. package/dist/service/registry/registry.constant.d.ts +23 -0
  35. package/dist/service/registry/registry.constant.d.ts.map +1 -0
  36. package/dist/service/registry/registry.interface.d.ts +15 -0
  37. package/dist/service/registry/registry.interface.d.ts.map +1 -0
  38. package/dist/service/{registry.service.d.ts → registry/registry.service.d.ts} +23 -15
  39. package/dist/service/registry/registry.service.d.ts.map +1 -0
  40. package/dist/service/service.interface.d.ts +0 -10
  41. package/dist/service/service.interface.d.ts.map +1 -1
  42. package/package.json +1 -1
  43. package/src/browser.ts +10 -9
  44. package/src/config/config.api.ts +72 -0
  45. package/src/{service → config}/config.interface.ts +1 -4
  46. package/src/config/index.ts +9 -0
  47. package/src/node/runtime-state/create-service-runtime-state-store.ts +1 -1
  48. package/src/node/runtime-state/service-runtime-state.types.ts +1 -1
  49. package/src/node/service-guard/registry-slot-guard-step.ts +4 -1
  50. package/src/node/service-guard/run-service-guard-tick.ts +1 -1
  51. package/src/node/service-guard/service-guard.interface.ts +1 -1
  52. package/src/node/service-host/claim-registry-slot.ts +2 -2
  53. package/src/node/service-host/service-host.ts +2 -2
  54. package/src/node/service-host/single-process-service.ts +1 -1
  55. package/src/service/index.ts +30 -40
  56. package/src/service/registry/index.ts +65 -0
  57. package/src/service/{registry-lifecycle.ts → registry/registry-lifecycle.ts} +3 -3
  58. package/src/service/{config.api.ts → registry/registry.api.ts} +6 -80
  59. package/src/service/registry/registry.constant.ts +17 -0
  60. package/src/service/registry/registry.interface.ts +16 -0
  61. package/src/service/{registry.service.ts → registry/registry.service.ts} +66 -65
  62. package/src/service/service.interface.ts +0 -12
  63. package/dist/chunks/task-queue-DCY_0Qj0.js.map +0 -1
  64. package/dist/service/config.api.d.ts.map +0 -1
  65. package/dist/service/config.interface.d.ts.map +0 -1
  66. package/dist/service/registry-lifecycle.d.ts.map +0 -1
  67. package/dist/service/registry.service.d.ts.map +0 -1
@@ -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
- GetConfigPayload,
14
- PostSystemRegistryConfigPayload,
15
- ResetSystemRegistryConfigPayload,
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.service";
33
+ } from "./registry/index";
45
34
  export {
46
- appendSystemRegistrySlots,
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.service";
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, ServiceSlotStatus } from "./service.interface";
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 "../core.api";
2
- import { createLogger } from "../shared/log";
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 "../core.api";
11
- import { generateResponse } from "../core.interface";
12
- import { CategoryConfig, type Config, type ConfigDetails, TARGET_SYSTEM_REGISTRY_KEY } from "./config.interface";
13
- import { type ServiceSlot, ServiceSlotStatus } from "./service.interface";
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 { isOptimisticLockError, updateTargetDetails } from "../core.api";
13
- import type { Node } from "../node/node.interface";
14
- import { createLogger } from "../shared/log";
15
- import { getConfig } from "./config.api";
16
- import { type Config, type ConfigDetails, TARGET_SYSTEM_REGISTRY_KEY } from "./config.interface";
17
- import { getService } from "./service.api";
18
- import {
19
- type Service,
20
- type ServiceDetails,
21
- type ServiceNodeSnapshot,
22
- type ServiceSlot,
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 AppendSystemRegistrySlotsInput {
89
- /** Logical service keys to declare with one new EMPTY slot each when missing. */
90
- serviceValues: string[];
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 AppendSystemRegistrySlotsOutcome {
93
+ export interface AppendSystemRegistryEmptySlotsOutcome {
96
94
  config: Config;
97
- /** Service keys that received a new EMPTY slot this run. */
98
- added: string[];
99
- /** Requested keys that already had at least one declared slot — no change. */
100
- skipped: string[];
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 logical service keys not yet declared.
622
- * Idempotent — skips keys that already appear in `details.objects`.
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 appendSystemRegistrySlots(
626
- input: AppendSystemRegistrySlotsInput,
627
- ): Promise<AppendSystemRegistrySlotsOutcome> {
628
- const serviceValues = [
629
- ...new Set(input.serviceValues.map((value) => value.trim()).filter((value) => value !== "")),
630
- ];
631
- if (serviceValues.length === 0) {
632
- throw new Error("[appendSystemRegistrySlots] serviceValues must not be empty");
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: "appendSystemRegistrySlots",
643
+ module: "appendSystemRegistryEmptySlots",
638
644
  traceId: input.traceId,
639
- labels: { serviceValues: serviceValues.join(",") },
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: { serviceValues },
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 added: string[] = [];
654
- const skipped: string[] = [];
655
- const nextSlots = [...slots];
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
- added.push(serviceValue);
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
- logger.info("registry 槽位追加成功", {
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: { added, skipped, attempt, revision: revision + 1 },
682
+ data: { serviceValue, appended: count, capacityBefore, capacityAfter, attempt },
688
683
  });
689
684
 
690
- return { config: updated, added, skipped };
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: { serviceValues, attempt, maxAttempts },
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: { serviceValues, attempt, message },
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
- "[appendSystemRegistrySlots] Optimistic lock retries exhausted",
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;