ga-plugins-cli 0.1.0 → 0.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/config-patcher.d.ts +20 -50
- package/dist/config-patcher.d.ts.map +1 -1
- package/dist/config-patcher.js +138 -102
- package/dist/config-patcher.js.map +1 -1
- package/dist/index.js +41 -5
- package/dist/index.js.map +1 -1
- package/dist/installer.d.ts +0 -18
- package/dist/installer.d.ts.map +1 -1
- package/dist/installer.js +19 -39
- package/dist/installer.js.map +1 -1
- package/dist/types.d.ts +10 -6
- package/dist/types.d.ts.map +1 -1
- package/dist/uninstaller.d.ts +0 -23
- package/dist/uninstaller.d.ts.map +1 -1
- package/dist/uninstaller.js +22 -68
- package/dist/uninstaller.js.map +1 -1
- package/package.json +3 -2
- package/plugins/go-reviewer/.claude-plugin/plugin.json +12 -0
- package/plugins/go-reviewer/commands/go-review.md +424 -0
- package/plugins/go-reviewer/mcp-servers/go-reviewer-mcp/README.md +236 -0
- package/plugins/go-reviewer/mcp-servers/go-reviewer-mcp/main.go +678 -0
- package/plugins/go-scaffolder/.claude-plugin/plugin.json +12 -0
- package/plugins/go-scaffolder/commands/scaffold-service.md +802 -0
- package/plugins/go-scaffolder/reference-service/.env.example +27 -0
- package/plugins/go-scaffolder/reference-service/Dockerfile +55 -0
- package/plugins/go-scaffolder/reference-service/REFERENCE-SERVICE-NOTICE.md +104 -0
- package/plugins/go-scaffolder/reference-service/cmd/server/main.go +266 -0
- package/plugins/go-scaffolder/reference-service/config/config.go +67 -0
- package/plugins/go-scaffolder/reference-service/go.mod +17 -0
- package/plugins/go-scaffolder/reference-service/internal/domain/booking.go +118 -0
- package/plugins/go-scaffolder/reference-service/internal/handler/booking.go +242 -0
- package/plugins/go-scaffolder/reference-service/internal/handler/booking_test.go +451 -0
- package/plugins/go-scaffolder/reference-service/internal/repository/booking_postgres.go +124 -0
- package/plugins/go-scaffolder/reference-service/internal/usecase/booking.go +181 -0
- package/plugins/go-standards/.claude-plugin/plugin.json +22 -0
- package/plugins/go-standards/commands/go-standards-check.md +232 -0
- package/plugins/go-standards/skills/concurrency.md +336 -0
- package/plugins/go-standards/skills/config.md +267 -0
- package/plugins/go-standards/skills/error-handling.md +286 -0
- package/plugins/go-standards/skills/http-chi.md +390 -0
- package/plugins/go-standards/skills/logging-observability.md +340 -0
- package/plugins/go-standards/skills/naming-and-style.md +315 -0
- package/plugins/go-standards/skills/project-layout.md +313 -0
- package/plugins/go-standards/skills/testing.md +366 -0
- package/plugins/java2go-porter/.claude-plugin/plugin.json +21 -0
- package/plugins/java2go-porter/agents/analyzer.md +232 -0
- package/plugins/java2go-porter/agents/reviewer.md +241 -0
- package/plugins/java2go-porter/agents/test-pairer.md +365 -0
- package/plugins/java2go-porter/agents/translator.md +419 -0
- package/plugins/java2go-porter/commands/port-java-service.md +149 -0
- package/plugins/java2go-porter/skills/idiom-mapping.md +75 -0
- package/plugins/migration-safety/.claude-plugin/plugin.json +20 -0
- package/plugins/migration-safety/commands/gen-characterization-test.md +452 -0
- package/plugins/migration-safety/commands/strangler-plan.md +356 -0
- package/plugins/migration-safety/skills/strangler-fig.md +382 -0
|
@@ -0,0 +1,382 @@
|
|
|
1
|
+
# Skill: strangler-fig
|
|
2
|
+
|
|
3
|
+
Reference guide for the Strangler Fig migration strategy used at Garuda Airlines. This document is consumed by the `strangler-plan` command and is available to any agent or command in the migration-safety plugin.
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## What Is the Strangler Fig Pattern?
|
|
8
|
+
|
|
9
|
+
The Strangler Fig pattern (coined by Martin Fowler, named after a tropical plant that gradually replaces the host tree) is a strategy for incrementally migrating a legacy system to a new one. Instead of a big-bang rewrite — where the old system is replaced all at once — the Strangler Fig approach replaces the old system piece by piece, with both systems running in parallel until the old system is fully decommissioned.
|
|
10
|
+
|
|
11
|
+
At any point during migration:
|
|
12
|
+
- The **old system** (Java) is running and can serve 100% of traffic if the new system has problems.
|
|
13
|
+
- The **new system** (Go) receives an increasing percentage of traffic as confidence grows.
|
|
14
|
+
- A **gateway** (Kong, Nginx, ALB, Istio) routes traffic between the two systems, providing the control plane for the cutover.
|
|
15
|
+
|
|
16
|
+
The key property: **rollback is always available** until the old system is decommissioned. This is the fundamental safety guarantee.
|
|
17
|
+
|
|
18
|
+
---
|
|
19
|
+
|
|
20
|
+
## Why Strangler Fig for the GA Java→Go Migration?
|
|
21
|
+
|
|
22
|
+
The Garuda Airlines migration has specific characteristics that make Strangler Fig the right choice:
|
|
23
|
+
|
|
24
|
+
1. **300 Java services → 30 Go services** (10:1 consolidation). A big-bang rewrite would require all 300 services to be ready simultaneously. Strangler Fig allows migration service-by-service, endpoint-by-endpoint.
|
|
25
|
+
|
|
26
|
+
2. **Aviation criticality**. Booking, check-in, and loyalty services cannot tolerate extended outages. Strangler Fig keeps the Java service on standby, making rollback a 5-minute operation rather than a multi-hour recovery.
|
|
27
|
+
|
|
28
|
+
3. **Long migration timeline**. A 10:1 consolidation at this scale will take months. Strangler Fig allows business value delivery (and technical de-risking) incrementally throughout the timeline.
|
|
29
|
+
|
|
30
|
+
4. **Unknown unknowns**. Java/Spring Boot services often contain behaviors that are difficult to discover statically — timing-dependent behavior, caching effects, Spring AOP side effects. Running both systems in parallel and comparing production traffic reveals these discrepancies without outages.
|
|
31
|
+
|
|
32
|
+
---
|
|
33
|
+
|
|
34
|
+
## Migration Phases
|
|
35
|
+
|
|
36
|
+
### Phase 1: Shadow Mode (Optional but Recommended)
|
|
37
|
+
|
|
38
|
+
**What**: Go service receives a copy of every request (via gateway mirroring or dual-write) but its responses are discarded. Java service continues to serve all responses.
|
|
39
|
+
|
|
40
|
+
**Purpose**: validate Go service correctness against real production traffic without any user impact.
|
|
41
|
+
|
|
42
|
+
**When to use**: for high-risk services where even 5% canary traffic is too risky (e.g., payment processing, seat reservation).
|
|
43
|
+
|
|
44
|
+
**Gateway implementation concept**:
|
|
45
|
+
- Kong: `request-termination` + `http-log` to mirror to Go service
|
|
46
|
+
- Nginx: `mirror` directive (`mirror /internal/go-mirror;`)
|
|
47
|
+
- Istio: `mirror` field in VirtualService with `mirrorPercentage`
|
|
48
|
+
- AWS ALB: not natively supported — use a sidecar proxy
|
|
49
|
+
|
|
50
|
+
**Exit criteria**: Go service processes 24 hours of mirrored production traffic with zero errors logged.
|
|
51
|
+
|
|
52
|
+
---
|
|
53
|
+
|
|
54
|
+
### Phase 2: Canary (5% → 10%)
|
|
55
|
+
|
|
56
|
+
**What**: a small percentage of real production traffic is routed to the Go service. Both services run in full production mode.
|
|
57
|
+
|
|
58
|
+
**Purpose**: catch issues that shadow mode cannot reveal (e.g., Go service writes incorrect data to the shared DB, or produces responses that client apps cannot parse).
|
|
59
|
+
|
|
60
|
+
**Duration**: minimum 30 minutes at 5%. Extend to 2-4 hours if the domain is critical.
|
|
61
|
+
|
|
62
|
+
**Canary size decision**:
|
|
63
|
+
|
|
64
|
+
| Traffic Sensitivity | Starting Canary % |
|
|
65
|
+
|--------------------|--------------------|
|
|
66
|
+
| Low (internal APIs, batch endpoints) | 10-20% |
|
|
67
|
+
| Medium (customer-facing, non-transactional) | 5% |
|
|
68
|
+
| High (booking, payment, seat assignment) | 1-2% |
|
|
69
|
+
| Critical (real-time check-in, boarding gate) | Shadow mode first, then 1% |
|
|
70
|
+
|
|
71
|
+
**Monitoring during canary** (see Monitoring section below).
|
|
72
|
+
|
|
73
|
+
**Exit criteria**: canary percentage has been stable for the defined duration with error rate < 0.1% and latency within 20% of Java baseline.
|
|
74
|
+
|
|
75
|
+
---
|
|
76
|
+
|
|
77
|
+
### Phase 3: Ramp (25% → 50% → 75%)
|
|
78
|
+
|
|
79
|
+
**What**: incremental traffic increase in stages, with observation periods between stages.
|
|
80
|
+
|
|
81
|
+
**Ramp schedule** (adjust based on service criticality):
|
|
82
|
+
- Low risk: 5% → 50% → 100% (skip intermediate steps)
|
|
83
|
+
- Medium risk: 5% → 25% → 50% → 75% → 100%
|
|
84
|
+
- High risk: 5% → 10% → 25% → 50% → 75% → 100% with 1-hour soak at each step
|
|
85
|
+
|
|
86
|
+
**What to watch**: same metrics as canary, but also watch for load-dependent issues (connection pool exhaustion, GC pauses, Go goroutine leaks under sustained load).
|
|
87
|
+
|
|
88
|
+
---
|
|
89
|
+
|
|
90
|
+
### Phase 4: Full Cutover (100% Go)
|
|
91
|
+
|
|
92
|
+
**What**: all traffic for the migrated endpoints routes to Go service. Java service runs but receives zero traffic.
|
|
93
|
+
|
|
94
|
+
**Important**: this is NOT decommissioning. Java service stays running for the fallback window.
|
|
95
|
+
|
|
96
|
+
**Fallback window**: minimum 2 weeks. This covers:
|
|
97
|
+
- Business-cycle-specific bugs (e.g., a bug only triggered by monthly billing runs)
|
|
98
|
+
- Long-tail error scenarios that did not appear at < 100% traffic
|
|
99
|
+
- Edge cases discovered by customer support reports post-cutover
|
|
100
|
+
|
|
101
|
+
---
|
|
102
|
+
|
|
103
|
+
### Phase 5: Decommission
|
|
104
|
+
|
|
105
|
+
**What**: Java service is stopped, infrastructure is released, gateway routing to Java is removed.
|
|
106
|
+
|
|
107
|
+
**When**: after the fallback window with no rollback events.
|
|
108
|
+
|
|
109
|
+
**This step is irreversible** (within the 2-week archive window). It should require explicit team sign-off.
|
|
110
|
+
|
|
111
|
+
---
|
|
112
|
+
|
|
113
|
+
## Anti-Corruption Layer (ACL) Pattern
|
|
114
|
+
|
|
115
|
+
### When to Use It
|
|
116
|
+
|
|
117
|
+
An Anti-Corruption Layer is needed when the Java and Go service have **different request or response shapes** for the same logical operation. This can happen when:
|
|
118
|
+
|
|
119
|
+
- The 10:1 consolidation produces a Go service with a unified API that differs from the individual Java APIs
|
|
120
|
+
- The Go service was designed with a cleaner schema (e.g., renamed fields, restructured JSON)
|
|
121
|
+
- The Java service used non-standard date formats or snake_case vs. camelCase fields
|
|
122
|
+
|
|
123
|
+
### What the ACL Does
|
|
124
|
+
|
|
125
|
+
The ACL is a translation layer that sits between the gateway and the Go service (or between the client and the gateway). It:
|
|
126
|
+
- Transforms incoming requests from the old (Java) schema to the new (Go) schema
|
|
127
|
+
- Transforms outgoing responses from the new (Go) schema back to the old (Java) schema
|
|
128
|
+
- Is transparent to the client — clients continue sending/receiving Java-compatible formats during the migration
|
|
129
|
+
|
|
130
|
+
### Where to Implement It
|
|
131
|
+
|
|
132
|
+
Options (choose one):
|
|
133
|
+
|
|
134
|
+
| Location | Pros | Cons |
|
|
135
|
+
|----------|------|------|
|
|
136
|
+
| Gateway plugin (e.g., Kong transformer plugin) | No code in services; centralized | Gateway-specific; harder to test |
|
|
137
|
+
| Sidecar on Go service | Service-independent; testable | More infrastructure |
|
|
138
|
+
| Inside the Go service handler | Easiest to implement | Couples migration logic into product code |
|
|
139
|
+
| Client-side versioned SDK | Clients control migration pace | Requires client coordination |
|
|
140
|
+
|
|
141
|
+
**Garuda recommendation**: gateway plugin for simple field renames; sidecar for complex structural differences. Remove the ACL layer once all clients are updated to the new schema.
|
|
142
|
+
|
|
143
|
+
### Removing the ACL
|
|
144
|
+
|
|
145
|
+
Plan to remove the ACL after all clients are migrated to the new Go API. Do not leave the ACL permanently — it becomes a maintenance burden and a source of subtle bugs.
|
|
146
|
+
|
|
147
|
+
---
|
|
148
|
+
|
|
149
|
+
## Traffic Splitting Patterns by Gateway Type
|
|
150
|
+
|
|
151
|
+
### Kong Gateway
|
|
152
|
+
|
|
153
|
+
```yaml
|
|
154
|
+
# Weighted upstream
|
|
155
|
+
_format_version: "3.0"
|
|
156
|
+
upstreams:
|
|
157
|
+
- name: booking-upstream
|
|
158
|
+
targets:
|
|
159
|
+
- target: booking-java-svc.internal:8080
|
|
160
|
+
weight: 95
|
|
161
|
+
- target: flight-ops-svc.internal:8081
|
|
162
|
+
weight: 5
|
|
163
|
+
services:
|
|
164
|
+
- name: booking-service
|
|
165
|
+
host: booking-upstream
|
|
166
|
+
routes:
|
|
167
|
+
- name: booking-routes
|
|
168
|
+
paths: ["/api/v1/bookings"]
|
|
169
|
+
```
|
|
170
|
+
|
|
171
|
+
Adjust `weight` values at each ramp step.
|
|
172
|
+
|
|
173
|
+
### Nginx
|
|
174
|
+
|
|
175
|
+
```nginx
|
|
176
|
+
# In upstream block:
|
|
177
|
+
split_clients "${remote_addr}${request_uri}" $backend {
|
|
178
|
+
5% go_upstream;
|
|
179
|
+
* java_upstream;
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
upstream java_upstream { server booking-java-svc.internal:8080; }
|
|
183
|
+
upstream go_upstream { server flight-ops-svc.internal:8081; }
|
|
184
|
+
|
|
185
|
+
location /api/v1/bookings {
|
|
186
|
+
proxy_pass http://$backend;
|
|
187
|
+
}
|
|
188
|
+
```
|
|
189
|
+
|
|
190
|
+
Adjust the percentage in `split_clients` at each ramp step. Reload Nginx config: `nginx -s reload`.
|
|
191
|
+
|
|
192
|
+
### AWS ALB
|
|
193
|
+
|
|
194
|
+
Traffic weighting is done via weighted target groups on ALB listener rules:
|
|
195
|
+
|
|
196
|
+
```json
|
|
197
|
+
{
|
|
198
|
+
"Type": "forward",
|
|
199
|
+
"ForwardConfig": {
|
|
200
|
+
"TargetGroups": [
|
|
201
|
+
{ "TargetGroupArn": "<JAVA_TG_ARN>", "Weight": 95 },
|
|
202
|
+
{ "TargetGroupArn": "<GO_TG_ARN>", "Weight": 5 }
|
|
203
|
+
],
|
|
204
|
+
"StickinessConfig": {
|
|
205
|
+
"Enabled": false
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
```
|
|
210
|
+
|
|
211
|
+
Update via: `aws elbv2 modify-rule --rule-arn <RULE_ARN> --actions <above JSON>`.
|
|
212
|
+
|
|
213
|
+
### Istio / Envoy
|
|
214
|
+
|
|
215
|
+
```yaml
|
|
216
|
+
apiVersion: networking.istio.io/v1alpha3
|
|
217
|
+
kind: VirtualService
|
|
218
|
+
metadata:
|
|
219
|
+
name: booking-vs
|
|
220
|
+
spec:
|
|
221
|
+
hosts:
|
|
222
|
+
- booking-svc
|
|
223
|
+
http:
|
|
224
|
+
- match:
|
|
225
|
+
- uri:
|
|
226
|
+
prefix: /api/v1/bookings
|
|
227
|
+
route:
|
|
228
|
+
- destination:
|
|
229
|
+
host: booking-java-svc
|
|
230
|
+
port: number: 8080
|
|
231
|
+
weight: 95
|
|
232
|
+
- destination:
|
|
233
|
+
host: flight-ops-svc
|
|
234
|
+
port: number: 8081
|
|
235
|
+
weight: 5
|
|
236
|
+
```
|
|
237
|
+
|
|
238
|
+
Apply: `kubectl apply -f booking-vs.yaml`. Update `weight` values at each ramp step.
|
|
239
|
+
|
|
240
|
+
---
|
|
241
|
+
|
|
242
|
+
## Fallback Strategy
|
|
243
|
+
|
|
244
|
+
### How to Roll Back (At Any Phase)
|
|
245
|
+
|
|
246
|
+
The rollback procedure is the same at every phase before decommissioning:
|
|
247
|
+
|
|
248
|
+
1. **Update gateway**: route 100% of traffic back to Java service (same change as forward routing, reversed)
|
|
249
|
+
2. **Verify Java is healthy**: check error rate and latency return to pre-migration baseline
|
|
250
|
+
3. **Notify team**: post to incident channel, tag on-call
|
|
251
|
+
4. **Do NOT restart the Go service** (keep it running for log inspection)
|
|
252
|
+
5. **Write incident report**: what triggered rollback, what was the observed behavior
|
|
253
|
+
|
|
254
|
+
Estimated rollback time: **< 5 minutes** for gateway-level rollback.
|
|
255
|
+
|
|
256
|
+
### Decision Authority
|
|
257
|
+
|
|
258
|
+
Any engineer in the on-call rotation can initiate rollback without management approval. Do not wait for a meeting — roll back first, investigate later.
|
|
259
|
+
|
|
260
|
+
### After Rolling Back
|
|
261
|
+
|
|
262
|
+
1. Collect Go service logs from the affected period
|
|
263
|
+
2. Compare Go service behavior with Java service behavior (request/response logs)
|
|
264
|
+
3. Write a bug report against the Go service
|
|
265
|
+
4. Do not re-attempt cutover until the root cause is confirmed fixed and characterization tests are updated to cover the bug case
|
|
266
|
+
|
|
267
|
+
---
|
|
268
|
+
|
|
269
|
+
## Monitoring During Cutover
|
|
270
|
+
|
|
271
|
+
### Metrics to Watch
|
|
272
|
+
|
|
273
|
+
| Metric | Description | Alert Threshold |
|
|
274
|
+
|--------|-------------|----------------|
|
|
275
|
+
| HTTP 5xx error rate | Unhandled errors in Go service | > 0.1% of requests |
|
|
276
|
+
| HTTP 4xx error rate | Client errors — watch for increases (may indicate schema mismatch) | > 20% increase from Java baseline |
|
|
277
|
+
| p99 latency | 99th percentile response time | > 20% above Java baseline |
|
|
278
|
+
| p50 latency | Median response time | > 10% above Java baseline |
|
|
279
|
+
| Request throughput | Requests/second reaching Go service | < 10% of expected (may indicate routing failure) |
|
|
280
|
+
| DB connection pool usage | Go service pool utilization | > 80% |
|
|
281
|
+
| Go goroutine count | Active goroutines (Go-specific: indicates leaks) | > 2x expected per-RPS |
|
|
282
|
+
| Business KPIs (domain-specific) | e.g., booking completion rate, seat availability accuracy | > 0.5% degradation |
|
|
283
|
+
|
|
284
|
+
### Log Correlation
|
|
285
|
+
|
|
286
|
+
During canary and ramp phases, both Java and Go services are processing requests. To correlate:
|
|
287
|
+
- Use `X-Request-ID` header propagated from the gateway — both services should log this
|
|
288
|
+
- Use distributed tracing (OpenTelemetry) if available — go-ga-lib should provide a tracing middleware
|
|
289
|
+
- Compare error patterns: a spike in Go errors with no corresponding Java errors indicates a Go-specific bug
|
|
290
|
+
|
|
291
|
+
### Grafana Dashboard Checklist
|
|
292
|
+
|
|
293
|
+
Set up the following panels before starting cutover:
|
|
294
|
+
|
|
295
|
+
- [ ] Go service error rate (5xx) over time
|
|
296
|
+
- [ ] Java service error rate (5xx) over time (should remain flat)
|
|
297
|
+
- [ ] Go vs. Java p99 latency side-by-side comparison
|
|
298
|
+
- [ ] Traffic split percentage over time (shows canary/ramp progression)
|
|
299
|
+
- [ ] Business KPI over time (domain-specific — e.g., "bookings created per minute")
|
|
300
|
+
- [ ] Go service DB query duration
|
|
301
|
+
- [ ] Go service goroutine count
|
|
302
|
+
|
|
303
|
+
---
|
|
304
|
+
|
|
305
|
+
## Data Migration Considerations
|
|
306
|
+
|
|
307
|
+
### During Parallel Operation (Steps 1-5)
|
|
308
|
+
|
|
309
|
+
If Go and Java services share the same database:
|
|
310
|
+
- **Go writes, Java reads**: generally safe. Ensure Go does not write schemas incompatible with what Java expects (e.g., new NOT NULL columns with no default).
|
|
311
|
+
- **Both writing to same table**: safe only if write operations are idempotent or there is no contention. If both services can write to the same row, implement optimistic locking.
|
|
312
|
+
- **Go reads new DB schema, Java reads old**: use a compatibility view or migration approach that keeps the old columns populated.
|
|
313
|
+
|
|
314
|
+
### Schema Migration Strategy
|
|
315
|
+
|
|
316
|
+
1. **Expand**: add new columns/tables needed by Go service. Keep old columns. Both Java and Go work.
|
|
317
|
+
2. **Migrate**: during ramp phase, backfill any data that Go service writes differently.
|
|
318
|
+
3. **Contract** (only after Java decommissioned): remove old columns/tables that Java needed but Go does not.
|
|
319
|
+
|
|
320
|
+
Never run the **Contract** step while Java is still running.
|
|
321
|
+
|
|
322
|
+
### Eventual Consistency Sync
|
|
323
|
+
|
|
324
|
+
If Go and Java services write to DIFFERENT databases (possible in the 10:1 consolidation):
|
|
325
|
+
- Implement a sync job that copies Java DB writes to Go DB during the parallel period
|
|
326
|
+
- Or implement dual-writes at the application level (write to both DBs for critical entities)
|
|
327
|
+
- Remove the sync job immediately after Java decommissioning — it is a temporary migration artifact
|
|
328
|
+
|
|
329
|
+
---
|
|
330
|
+
|
|
331
|
+
## Common Pitfalls
|
|
332
|
+
|
|
333
|
+
### 1. Session State in Java Services
|
|
334
|
+
|
|
335
|
+
Java services using `HttpSession` or Spring Session store state in memory or in a session store (Redis, JDBC). Go services have no equivalent by default.
|
|
336
|
+
|
|
337
|
+
**Risk**: users mid-session during a canary may have their session routed to the Go service, which cannot find the session.
|
|
338
|
+
|
|
339
|
+
**Mitigation**: use sticky sessions at the gateway during migration (route a user to the same service for the duration of their session), then switch fully to Go. Alternatively, externalize session state before migration and ensure Go service reads from the same session store.
|
|
340
|
+
|
|
341
|
+
### 2. Caching Inconsistencies
|
|
342
|
+
|
|
343
|
+
Java services using `@Cacheable` with local caches (Caffeine, EhCache) have caches that are NOT shared with the Go service. During canary, a request going to Java may get a cached response while the same request going to Go hits the DB and gets a different (more current) response.
|
|
344
|
+
|
|
345
|
+
**Mitigation**: use a shared distributed cache (Redis) before starting canary, so both Java and Go read/write the same cache. Or accept that canary will bypass Java caches and monitor for increased DB load.
|
|
346
|
+
|
|
347
|
+
### 3. Distributed Transactions
|
|
348
|
+
|
|
349
|
+
If a Java service starts a distributed transaction (XA, Saga, or CQRS event) and the Go service is responsible for part of the flow, there is no automatic coordination.
|
|
350
|
+
|
|
351
|
+
**Mitigation**: do not cut over endpoints that participate in distributed transactions until all participants are ready to migrate together. Migrate the entire saga/workflow atomically, not endpoint by endpoint.
|
|
352
|
+
|
|
353
|
+
### 4. Hidden Shared State in Java
|
|
354
|
+
|
|
355
|
+
Java services with static fields, thread-local state, or Singleton caches that accumulate state across requests may behave differently under canary. For example: a Java Singleton that caches flight availability data will have a warm cache after hours of operation, while the Go service starts cold.
|
|
356
|
+
|
|
357
|
+
**Mitigation**: identify all stateful caches (from ANALYSIS.md) and pre-warm Go service caches before canary, or account for cold-start behavior in the 5% canary phase.
|
|
358
|
+
|
|
359
|
+
### 5. Time-Zone and Date Format Differences
|
|
360
|
+
|
|
361
|
+
Java uses `ZonedDateTime` with explicit timezone handling; Go uses `time.Time` (always UTC by default). A subtle difference in timezone serialization (e.g., Java returns `"2024-03-15T14:30:00+07:00"` and Go returns `"2024-03-15T07:30:00Z"`) can break clients.
|
|
362
|
+
|
|
363
|
+
**Mitigation**: add explicit serialization tests in characterization tests. Verify JSON date format matches between Java and Go responses.
|
|
364
|
+
|
|
365
|
+
---
|
|
366
|
+
|
|
367
|
+
## GA-Specific Notes: 10→1 Consolidation
|
|
368
|
+
|
|
369
|
+
The Garuda Airlines migration consolidates 10 Java services into 1 Go service. The Strangler Fig pattern must be applied at the **endpoint group** level, not at the service level, because:
|
|
370
|
+
|
|
371
|
+
- One Go service (`flight-ops-svc`) may absorb endpoints from 10 different Java services (`booking-java-svc`, `seat-java-svc`, `check-in-java-svc`, ...)
|
|
372
|
+
- Each endpoint group from each Java service must go through its own canary → ramp → cutover cycle
|
|
373
|
+
- The Go service can receive 100% of traffic for `POST /api/v1/bookings` while still receiving 0% of traffic for `POST /api/v1/check-in` (from a different Java service, not yet migrated)
|
|
374
|
+
- The gateway must support endpoint-level traffic splitting, not just service-level
|
|
375
|
+
|
|
376
|
+
**Implication for the strangler-plan command**: the `<endpoint-list>` parameter in each plan should cover only the endpoints being migrated in THIS phase, not all endpoints eventually destined for the Go service.
|
|
377
|
+
|
|
378
|
+
**Consolidation cutover sequence suggestion**:
|
|
379
|
+
1. Migrate the simplest Java service endpoints first (fewest dependencies, lowest traffic)
|
|
380
|
+
2. Build confidence with the Go service under real production load before migrating complex endpoints
|
|
381
|
+
3. Do not attempt full consolidation (all 10 Java services → 1 Go service) until at least 3 Java services have been successfully migrated and decommissioned
|
|
382
|
+
4. The architecture team must own the consolidation sequencing — the migration-safety plugin does not decide which endpoints to migrate in which order
|