Files
Lucas Berger 8e8a5f9dc3 docs(16-04): complete Batch UI GraphQL migration plan
- Created 16-04-SUMMARY.md with full execution details
- Updated STATE.md: Phase 16 in progress (1/5 plans)
- Recorded decisions: 5 normalizer nodes, 15s timeout
- Updated progress: v1.4 now 30% complete (3/10 plans)
2026-02-09 10:24:47 -05:00

8.6 KiB

phase, plan, subsystem, tags, dependency_graph, tech_stack, key_files, decisions, metrics
phase plan subsystem tags dependency_graph tech_stack key_files decisions metrics
16-api-migration 04 n8n-batch-ui
api-migration
graphql
batch-operations
normalizer
requires provides affects
phase plan artifact
15 02 GraphQL Response Normalizer pattern
artifact consumers
n8n-batch-ui.json with Unraid GraphQL API
Main workflow Batch UI callers
Batch container selection flow
All 5 batch action paths (mode, toggle, exec, nav, clear)
added patterns
GraphQL API queries with normalizer transformation
5 identical normalizer nodes (one per query path)
Docker API contract compatibility layer
created modified
path lines_changed description
n8n-batch-ui.json 354 Migrated all 5 container queries from Docker socket proxy to Unraid GraphQL API with normalizer nodes
summary rationale alternatives
5 identical normalizer nodes instead of shared utility node n8n sub-workflows cannot share nodes across independent paths - each path needs its own node instance
Single normalizer with complex routing (rejected: architectural constraint)
summary rationale alternatives
15-second timeout for GraphQL queries myunraid.net cloud relay adds 200-500ms latency, increased from 5s Docker socket proxy timeout for safety margin
Keep 5s timeout (rejected: insufficient for cloud relay)
30s timeout (rejected: too long for UI interaction)
summary rationale alternatives
Keep full PrefixedID in normalizer output Container ID Registry (Phase 15) handles translation downstream, normalizer preserves complete Unraid ID
Truncate to 12-char in normalizer (rejected: breaks registry lookup)
duration_minutes completed_date tasks_completed files_modified nodes_added nodes_modified connections_rewired
2 2026-02-09 1 1 5 5 15

Phase 16 Plan 04: Batch UI GraphQL Migration Summary

One-liner: Migrated n8n-batch-ui.json from Docker socket proxy to Unraid GraphQL API with 5 normalizer nodes preserving zero-change contract for downstream consumers

What Was Delivered

Core Implementation

n8n-batch-ui.json transformation (nodes: 17 → 22):

All 5 container listing queries migrated from Docker socket proxy to Unraid GraphQL API:

  1. Fetch Containers For Mode - Initial batch selection entry
  2. Fetch Containers For Update - After toggling container selection
  3. Fetch Containers For Exec - Before batch action execution
  4. Fetch Containers For Nav - Page navigation
  5. Fetch Containers For Clear - After clearing selection

For each query path:

[upstream] → HTTP Request (GraphQL) → Normalizer (Code) → [existing downstream]

HTTP Request nodes transformed:

  • Method: GETPOST
  • URL: http://docker-socket-proxy:2375/containers/json?all=true={{ $env.UNRAID_HOST }}/graphql
  • Query: query { docker { containers { id names state image } } }
  • Headers: Content-Type: application/json, x-api-key: ={{ $env.UNRAID_API_KEY }}
  • Timeout: 5000ms → 15000ms (cloud relay safety margin)
  • Error handling: continueRegularOutput

GraphQL Response Normalizer (5 identical nodes):

  • Input: {data: {docker: {containers: [{id, names, state, image}]}}}
  • Output: [{Id, Names, State, Status, Image, _unraidId}] (Docker API contract)
  • State mapping: RUNNING → running, STOPPED → exited, PAUSED → paused
  • n8n multi-item output format: [{json: container}, ...]

Downstream Code nodes (UNCHANGED - verified):

  • Build Batch Keyboard (bitmap encoding, pagination, keyboard building)
  • Handle Toggle (bitmap toggle logic)
  • Handle Exec (bitmap to names resolution, confirmation routing)
  • Rebuild Keyboard After Toggle (bitmap decoding, keyboard rebuild)
  • Rebuild Keyboard For Nav (page navigation, keyboard rebuild)
  • Rebuild Keyboard After Clear (reset to empty bitmap)
  • Handle Cancel (return to container list)

All bitmap encoding, container sorting, pagination, and keyboard building logic preserved byte-for-byte.

Zero-Change Migration Pattern

Docker API contract fields preserved:

  • Id - Full Unraid PrefixedID (Container ID Registry handles translation)
  • Names - Array with / prefix (e.g., ["/plex"])
  • State - Lowercase state (running, exited, paused)
  • Status - Same as State (Docker API convention)
  • Image - Empty string (not queried, not used by batch UI)

Why this works:

  • All downstream Code nodes reference Names[0], State, Id.substring(0, 12)
  • Normalizer ensures these fields exist in the exact format expected
  • Bitmap encoding uses array indices, not IDs (migration transparent)
  • Container sorting uses state and name (both preserved)

Deviations from Plan

None - plan executed exactly as written.

Authentication Gates

None encountered.

Testing & Verification

Automated verification (all passed):

  1. ✓ Zero HTTP Request nodes contain "docker-socket-proxy"
  2. ✓ All 5 HTTP Request nodes use POST to $env.UNRAID_HOST/graphql
  3. ✓ 5 GraphQL Response Normalizer Code nodes exist (one per query path)
  4. ✓ All downstream Code nodes byte-for-byte identical to pre-migration
  5. ✓ Node count: 22 (17 original + 5 normalizers)
  6. ✓ All connection chains valid (15 connections verified)
  7. ✓ Pushed to n8n successfully (HTTP 200, workflow ID ZJhnGzJT26UUmW45)

Connection chain validation:

  • Route Batch UI Action → Fetch Containers For Mode → Normalizer → Build Batch Keyboard ✓
  • Needs Keyboard Update? → Fetch Containers For Update → Normalizer → Rebuild Keyboard ✓
  • Route Batch UI Action → Fetch Containers For Exec → Normalizer → Handle Exec ✓
  • Handle Nav → Fetch Containers For Nav → Normalizer → Rebuild Keyboard For Nav ✓
  • Handle Clear → Fetch Containers For Clear → Normalizer → Rebuild Keyboard After Clear ✓

Manual testing required:

  • Open Telegram bot, start batch selection (/batch command path)
  • Verify container list displays with correct names and states
  • Toggle container selection, verify checkmarks update correctly
  • Navigate between pages, verify pagination works
  • Execute batch start action, verify correct containers are started
  • Execute batch stop action, verify confirmation prompt appears
  • Clear selection, verify UI resets to empty state

Impact Assessment

User-facing changes:

  • None - UI and behavior identical to pre-migration

System changes:

  • Removed dependency on docker-socket-proxy for batch container listing
  • Added dependency on Unraid GraphQL API + myunraid.net cloud relay
  • Increased query timeout from 5s to 15s (cloud relay latency)
  • Added 5 normalizer nodes (increased workflow complexity slightly)

Performance impact:

  • Query latency: +200-500ms (cloud relay overhead vs local Docker socket)
  • User-perceivable: Minimal (batch selection already async)
  • Timeout safety: 15s provides 30x safety margin over typical 500ms latency

Risk mitigation:

  • GraphQL error handling: normalizer throws on errors → captured by n8n error handling
  • Invalid response structure: explicit validation with descriptive errors
  • State mapping: comprehensive (RUNNING, STOPPED, PAUSED) + fallback to lowercase

Known Limitations

Current state:

  • Image field empty (not queried) - batch UI doesn't use it, no impact
  • No retry logic on GraphQL failures (relies on n8n default retry)
  • Cloud relay adds latency (200-500ms) - acceptable for batch operations

Future improvements:

  • Could add retry logic with exponential backoff for cloud relay transient failures
  • Could query image field if future batch features need it
  • Could implement local caching if latency becomes problematic (unlikely for batch ops)

Next Steps

Immediate:

  • Phase 16 Plan 05: Migrate remaining workflows (Container Status, Confirmation, etc.)

Follow-up:

  • Manual testing of batch selection end-to-end
  • Monitor cloud relay latency in production
  • Consider removing docker-socket-proxy container once all migrations complete

Self-Check: PASSED

Files verified:

  • ✓ FOUND: n8n-batch-ui.json (modified, 22 nodes)
  • ✓ FOUND: n8n-batch-ui.json pushed to n8n (HTTP 200)

Commits verified:

  • ✓ FOUND: 73a01b6 (feat(16-04): migrate Batch UI to Unraid GraphQL API)

Claims verified:

  • ✓ 5 GraphQL Response Normalizer nodes exist in workflow
  • ✓ All 5 HTTP Request nodes use GraphQL (verified in workflow JSON)
  • ✓ Zero docker-socket-proxy references (verified in workflow JSON)
  • ✓ Downstream Code nodes unchanged (verified byte-for-byte during transformation)

All summary claims verified against actual implementation.