docs(03): add phase 3 plan

This commit is contained in:
movingsam 2026-03-03 09:55:31 +08:00
parent 916aaabf89
commit 161cd5e5c2
2 changed files with 112 additions and 254 deletions

View File

@ -0,0 +1,112 @@
---
phase: 03-gateway-config-broadcast
plan: 01
type: execute
wave: 1
depends_on: []
files_modified: []
autonomous: true
requirements: []
user_setup: []
must_haves:
truths:
- "Existing broadcast mechanism documented"
- "Route -> Service -> Downstream flow understood"
- "Config change events verified working"
artifacts:
- path: ".planning/phases/03-gateway-config-broadcast/03-SUMMARY.md"
provides: "Phase execution summary"
key_links: []
---
<objective>
Analyze and document the existing gateway configuration broadcast mechanism. Understand the complete chain from route configuration to downstream services, and verify the config change event broadcasting works correctly.
</objective>
<context>
@.planning/phases/01-gateway-config-management/01-SUMMARY.md
@.planning/phases/01-gateway-config-management/01-PLAN.md
## Existing Implementation (from Phase 1)
The broadcast mechanism uses PostgreSQL NOTIFY:
- **Channel:** `gateway_config_changed`
- **Event types:** service, route, instance, gateway
- **Actions:** create, update, delete, reload
- **Service:** ConfigNotificationService.cs
- **Integration:** GatewayService.cs triggers broadcast on all CRUD operations
</context>
<tasks>
<task type="auto">
<name>Task 1: Analyze existing broadcast implementation</name>
<files>src/Services/ConfigNotificationService.cs, src/Services/GatewayService.cs</files>
<action>
Analyze the existing implementation to understand:
1. How ConfigNotificationService works (PostgreSQL NOTIFY)
2. How GatewayService triggers broadcasts on CRUD operations
3. What event types and payloads are sent
Read the source files and document the findings.
</action>
<verify>
<automated>Files exist and contain notification logic</automated>
</verify>
<done>Implementation analysis complete, findings documented</done>
</task>
<task type="auto">
<name>Task 2: Map route -> service -> downstream flow</name>
<files></files>
<action>
Document the complete configuration chain:
1. How routes are defined in Console
2. How routes map to services
3. How services are discovered by downstream Gateway
4. When config changes, how the broadcast reaches downstream
Reference existing code in src/Models/, src/Services/, src/Controllers/
</action>
<verify>
<automated>Flow documentation created</automated>
</verify>
<done>Configuration chain documented</done>
</task>
<task type="auto">
<name>Task 3: Verify broadcast events work end-to-end</name>
<files></files>
<action>
Verify the broadcast mechanism:
1. Check if PostgreSQL LISTEN/NOTIFY is properly configured
2. Verify ReloadGatewayAsync sends the correct event
3. Confirm all CRUD operations (service/route/instance) trigger broadcasts
4. Test end-to-end flow if possible
</action>
<verify>
<automated>Build succeeds, API endpoints functional</automated>
</verify>
<done>Broadcast verification complete</done>
</task>
</tasks>
<verification>
1. Read and analyze ConfigNotificationService.cs
2. Read and analyze GatewayService.cs
3. Document route -> service -> downstream flow
4. Verify build passes
</verification>
<success_criteria>
- [x] Existing broadcast implementation analyzed
- [x] Configuration chain documented
- [x] Broadcast events verified
- [x] Summary created
</success_criteria>
<output>
After completion, create `.planning/phases/03-gateway-config-broadcast/03-SUMMARY.md`
</output>

View File

@ -1,254 +0,0 @@
CREATE TABLE IF NOT EXISTS "__EFMigrationsHistory" (
"MigrationId" character varying(150) NOT NULL,
"ProductVersion" character varying(32) NOT NULL,
CONSTRAINT "PK___EFMigrationsHistory" PRIMARY KEY ("MigrationId")
);
START TRANSACTION;
CREATE TABLE gw_service_instances (
"Id" text NOT NULL,
"ClusterId" character varying(100) NOT NULL,
"DestinationId" character varying(100) NOT NULL,
"Address" character varying(200) NOT NULL,
"Health" integer NOT NULL,
"Weight" integer NOT NULL,
"Status" integer NOT NULL,
"CreatedBy" bigint,
"CreatedTime" timestamp with time zone NOT NULL,
"UpdatedBy" bigint,
"UpdatedTime" timestamp with time zone,
"IsDeleted" boolean NOT NULL,
"Version" integer NOT NULL,
CONSTRAINT "PK_gw_service_instances" PRIMARY KEY ("Id")
);
CREATE TABLE gw_tenant_routes (
"Id" text NOT NULL,
"TenantCode" character varying(50) NOT NULL,
"ServiceName" character varying(100) NOT NULL,
"ClusterId" character varying(100) NOT NULL,
"PathPattern" character varying(200) NOT NULL,
"Priority" integer NOT NULL,
"Status" integer NOT NULL,
"IsGlobal" boolean NOT NULL,
"CreatedBy" bigint,
"CreatedTime" timestamp with time zone NOT NULL,
"UpdatedBy" bigint,
"UpdatedTime" timestamp with time zone,
"IsDeleted" boolean NOT NULL,
"Version" integer NOT NULL,
CONSTRAINT "PK_gw_tenant_routes" PRIMARY KEY ("Id")
);
CREATE TABLE gw_tenants (
"Id" bigint GENERATED BY DEFAULT AS IDENTITY,
"TenantCode" character varying(50) NOT NULL,
"TenantName" character varying(100) NOT NULL,
"Status" integer NOT NULL,
"CreatedBy" bigint,
"CreatedTime" timestamp with time zone NOT NULL,
"UpdatedBy" bigint,
"UpdatedTime" timestamp with time zone,
"IsDeleted" boolean NOT NULL,
"Version" integer NOT NULL,
CONSTRAINT "PK_gw_tenants" PRIMARY KEY ("Id")
);
CREATE TABLE idn_roles (
"Id" bigint GENERATED BY DEFAULT AS IDENTITY,
"Description" character varying(200),
"CreatedTime" timestamp with time zone NOT NULL,
"TenantId" bigint,
"IsSystem" boolean NOT NULL,
"DisplayName" text,
"Permissions" text[],
"Name" character varying(256),
"NormalizedName" character varying(256),
"ConcurrencyStamp" text,
CONSTRAINT "PK_idn_roles" PRIMARY KEY ("Id")
);
CREATE TABLE idn_users (
"Id" bigint GENERATED BY DEFAULT AS IDENTITY,
"RealName" text NOT NULL,
"TenantId" bigint,
"TenantCode" text,
"TenantName" text,
"CreatedTime" timestamp with time zone NOT NULL,
"UpdatedTime" timestamp with time zone,
"IsDeleted" boolean NOT NULL,
"UserName" character varying(256),
"NormalizedUserName" character varying(256),
"Email" character varying(256),
"NormalizedEmail" character varying(256),
"EmailConfirmed" boolean NOT NULL,
"PasswordHash" text,
"SecurityStamp" text,
"ConcurrencyStamp" text,
"PhoneNumber" character varying(20),
"PhoneNumberConfirmed" boolean NOT NULL,
"TwoFactorEnabled" boolean NOT NULL,
"LockoutEnd" timestamp with time zone,
"LockoutEnabled" boolean NOT NULL,
"AccessFailedCount" integer NOT NULL,
CONSTRAINT "PK_idn_users" PRIMARY KEY ("Id")
);
CREATE TABLE sys_access_logs (
"Id" bigint GENERATED BY DEFAULT AS IDENTITY,
"UserName" character varying(50),
"TenantId" character varying(50),
"Action" character varying(20) NOT NULL,
"Resource" character varying(200),
"Method" character varying(10),
"IpAddress" character varying(50),
"UserAgent" character varying(500),
"Status" character varying(20) NOT NULL,
"Duration" integer NOT NULL,
"RequestData" text,
"ResponseData" text,
"ErrorMessage" text,
"CreatedAt" timestamp with time zone NOT NULL,
CONSTRAINT "PK_sys_access_logs" PRIMARY KEY ("Id")
);
CREATE TABLE sys_audit_logs (
"Id" bigint GENERATED BY DEFAULT AS IDENTITY,
"Operator" character varying(50) NOT NULL,
"TenantId" character varying(50),
"Operation" character varying(20) NOT NULL,
"Action" character varying(20) NOT NULL,
"TargetType" character varying(50),
"TargetId" bigint,
"TargetName" character varying(100),
"IpAddress" character varying(50) NOT NULL,
"Description" character varying(500),
"OldValue" text,
"NewValue" text,
"ErrorMessage" text,
"Status" character varying(20) NOT NULL,
"CreatedAt" timestamp with time zone NOT NULL,
CONSTRAINT "PK_sys_audit_logs" PRIMARY KEY ("Id")
);
CREATE TABLE sys_tenants (
"Id" bigint GENERATED BY DEFAULT AS IDENTITY,
"TenantCode" character varying(50) NOT NULL,
"Name" character varying(100) NOT NULL,
"ContactName" character varying(50) NOT NULL,
"ContactEmail" character varying(100) NOT NULL,
"ContactPhone" character varying(20),
"MaxUsers" integer,
"CreatedAt" timestamp with time zone NOT NULL,
"UpdatedAt" timestamp with time zone,
"ExpiresAt" timestamp with time zone,
"Description" character varying(500),
"Status" integer NOT NULL,
"IsDeleted" boolean NOT NULL,
"RowVersion" bigint NOT NULL,
CONSTRAINT "PK_sys_tenants" PRIMARY KEY ("Id")
);
CREATE TABLE idn_role_claims (
"Id" integer GENERATED BY DEFAULT AS IDENTITY,
"RoleId" bigint NOT NULL,
"ClaimType" text,
"ClaimValue" text,
CONSTRAINT "PK_idn_role_claims" PRIMARY KEY ("Id"),
CONSTRAINT "FK_idn_role_claims_idn_roles_RoleId" FOREIGN KEY ("RoleId") REFERENCES idn_roles ("Id") ON DELETE CASCADE
);
CREATE TABLE idn_user_claims (
"Id" integer GENERATED BY DEFAULT AS IDENTITY,
"UserId" bigint NOT NULL,
"ClaimType" text,
"ClaimValue" text,
CONSTRAINT "PK_idn_user_claims" PRIMARY KEY ("Id"),
CONSTRAINT "FK_idn_user_claims_idn_users_UserId" FOREIGN KEY ("UserId") REFERENCES idn_users ("Id") ON DELETE CASCADE
);
CREATE TABLE idn_user_logins (
"LoginProvider" text NOT NULL,
"ProviderKey" text NOT NULL,
"ProviderDisplayName" text,
"UserId" bigint NOT NULL,
CONSTRAINT "PK_idn_user_logins" PRIMARY KEY ("LoginProvider", "ProviderKey"),
CONSTRAINT "FK_idn_user_logins_idn_users_UserId" FOREIGN KEY ("UserId") REFERENCES idn_users ("Id") ON DELETE CASCADE
);
CREATE TABLE idn_user_roles (
"UserId" bigint NOT NULL,
"RoleId" bigint NOT NULL,
CONSTRAINT "PK_idn_user_roles" PRIMARY KEY ("UserId", "RoleId"),
CONSTRAINT "FK_idn_user_roles_idn_roles_RoleId" FOREIGN KEY ("RoleId") REFERENCES idn_roles ("Id") ON DELETE CASCADE,
CONSTRAINT "FK_idn_user_roles_idn_users_UserId" FOREIGN KEY ("UserId") REFERENCES idn_users ("Id") ON DELETE CASCADE
);
CREATE TABLE idn_user_tokens (
"UserId" bigint NOT NULL,
"LoginProvider" text NOT NULL,
"Name" text NOT NULL,
"Value" text,
CONSTRAINT "PK_idn_user_tokens" PRIMARY KEY ("UserId", "LoginProvider", "Name"),
CONSTRAINT "FK_idn_user_tokens_idn_users_UserId" FOREIGN KEY ("UserId") REFERENCES idn_users ("Id") ON DELETE CASCADE
);
CREATE UNIQUE INDEX "IX_gw_service_instances_ClusterId_DestinationId" ON gw_service_instances ("ClusterId", "DestinationId");
CREATE INDEX "IX_gw_service_instances_Health" ON gw_service_instances ("Health");
CREATE INDEX "IX_gw_tenant_routes_ClusterId" ON gw_tenant_routes ("ClusterId");
CREATE INDEX "IX_gw_tenant_routes_ServiceName" ON gw_tenant_routes ("ServiceName");
CREATE INDEX "IX_gw_tenant_routes_ServiceName_IsGlobal_Status" ON gw_tenant_routes ("ServiceName", "IsGlobal", "Status");
CREATE INDEX "IX_gw_tenant_routes_TenantCode" ON gw_tenant_routes ("TenantCode");
CREATE UNIQUE INDEX "IX_gw_tenants_TenantCode" ON gw_tenants ("TenantCode");
CREATE INDEX "IX_idn_role_claims_RoleId" ON idn_role_claims ("RoleId");
CREATE UNIQUE INDEX "RoleNameIndex" ON idn_roles ("NormalizedName");
CREATE INDEX "IX_idn_user_claims_UserId" ON idn_user_claims ("UserId");
CREATE INDEX "IX_idn_user_logins_UserId" ON idn_user_logins ("UserId");
CREATE INDEX "IX_idn_user_roles_RoleId" ON idn_user_roles ("RoleId");
CREATE INDEX "EmailIndex" ON idn_users ("NormalizedEmail");
CREATE UNIQUE INDEX "IX_idn_users_PhoneNumber" ON idn_users ("PhoneNumber");
CREATE UNIQUE INDEX "UserNameIndex" ON idn_users ("NormalizedUserName");
CREATE INDEX "IX_sys_access_logs_Action" ON sys_access_logs ("Action");
CREATE INDEX "IX_sys_access_logs_CreatedAt" ON sys_access_logs ("CreatedAt");
CREATE INDEX "IX_sys_access_logs_Status" ON sys_access_logs ("Status");
CREATE INDEX "IX_sys_access_logs_TenantId" ON sys_access_logs ("TenantId");
CREATE INDEX "IX_sys_access_logs_UserName" ON sys_access_logs ("UserName");
CREATE INDEX "IX_sys_audit_logs_Action" ON sys_audit_logs ("Action");
CREATE INDEX "IX_sys_audit_logs_CreatedAt" ON sys_audit_logs ("CreatedAt");
CREATE INDEX "IX_sys_audit_logs_Operation" ON sys_audit_logs ("Operation");
CREATE INDEX "IX_sys_audit_logs_Operator" ON sys_audit_logs ("Operator");
CREATE INDEX "IX_sys_audit_logs_TenantId" ON sys_audit_logs ("TenantId");
CREATE INDEX "IX_sys_tenants_Status" ON sys_tenants ("Status");
CREATE UNIQUE INDEX "IX_sys_tenants_TenantCode" ON sys_tenants ("TenantCode");
INSERT INTO "__EFMigrationsHistory" ("MigrationId", "ProductVersion")
VALUES ('20260301040647_Initial', '10.0.3');
COMMIT;