Fix: Tracing toggle requires page refresh for Template and MessageProcessor artifacts (#437)#565
Fix: Tracing toggle requires page refresh for Template and MessageProcessor artifacts (#437)#565SasinduDilshara wants to merge 3 commits intowso2:mainfrom
Conversation
…cessor artifacts - Add tracingInSync/statisticsInSync fields to Template GraphQL type and enrich templatesByEnvironmentAndComponent resolver from reconcile state (Issue wso2#437) - Guard useEffect in EntryPoints.tsx from reverting optimistic toggle state when tracingInSync/statisticsInSync is false (stale heartbeat race condition) - Remove unsupported tracing field from MessageProcessor gqlFields in queries.ts - Track Template tracing/statistics observed state in writeObservedStateMI - Add test data and Ballerina tests covering in-sync / out-of-sync scenarios Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Issue Analysis — [Issue #437]: [MI] When tracing enabled/disabled it requires page refresh to see the effectClassification
Reproducibility
Root Cause AnalysisThe issue has three interacting layers: 1. Original root cause (largely addressed): 2. Residual root cause — incomplete 3. Stale heartbeat race (edge case, all types): Test Coverage Assessment
Fix Recommendations (for implementing agent)
|
| types:Template[] result = check storage:getTemplatesByEnvironmentAndComponent(environmentId, componentId); | ||
| if result.length() == 0 { |
There was a problem hiding this comment.
Log Improvement Suggestion No: 1
| types:Template[] result = check storage:getTemplatesByEnvironmentAndComponent(environmentId, componentId); | |
| if result.length() == 0 { | |
| types:Template[] result = check storage:getTemplatesByEnvironmentAndComponent(environmentId, componentId); | |
| log.info("Fetched templates for environment: " + environmentId + " and component: " + componentId + ", count: " + result.length().toString()); | |
| if result.length() == 0 { |
| } | ||
| map<map<types:ArtifactStateField>> sm = check storage:queryArtifactState(componentId, environmentId); | ||
| foreach types:Template a in result { |
There was a problem hiding this comment.
Log Improvement Suggestion No: 2
| } | |
| map<map<types:ArtifactStateField>> sm = check storage:queryArtifactState(componentId, environmentId); | |
| foreach types:Template a in result { | |
| } | |
| map<map<types:ArtifactStateField>> sm = check storage:queryArtifactState(componentId, environmentId); | |
| log.debug("Querying artifact state for component: " + componentId + " in environment: " + environmentId); | |
| foreach types:Template a in result { |
| foreach types:Template template in <types:Template[]>artifacts.templates { | ||
| entries.push([ | ||
| {artifactName: template.name, artifactType: "template"}, | ||
| {"tracing": template.tracing, "statistics": template.statistics} | ||
| ]); | ||
| } |
There was a problem hiding this comment.
Log Improvement Suggestion No: 3
| foreach types:Template template in <types:Template[]>artifacts.templates { | |
| entries.push([ | |
| {artifactName: template.name, artifactType: "template"}, | |
| {"tracing": template.tracing, "statistics": template.statistics} | |
| ]); | |
| } | |
| foreach types:Template template in <types:Template[]>artifacts.templates { | |
| log.info("Processing template artifact: " + template.name); | |
| entries.push([ | |
| {artifactName: template.name, artifactType: "template"}, | |
| {"tracing": template.tracing, "statistics": template.statistics} | |
| ]); | |
| } |
| function testTemplateQueryAcceptsTracingInSyncField() returns error? { | ||
| string query = string ` | ||
| query { | ||
| templatesByEnvironmentAndComponent( | ||
| environmentId: "${DEV_ENV_ID}", |
There was a problem hiding this comment.
Log Improvement Suggestion No: 4
| function testTemplateQueryAcceptsTracingInSyncField() returns error? { | |
| string query = string ` | |
| query { | |
| templatesByEnvironmentAndComponent( | |
| environmentId: "${DEV_ENV_ID}", | |
| @test:Config { | |
| groups: ["artifact-tracing", "template-tracing-schema"] | |
| } | |
| function testTemplateQueryAcceptsTracingInSyncField() returns error? { | |
| log:printInfo("Testing template query with tracingInSync field"); | |
| string query = string ` |
| `; | ||
|
|
||
| json response = check executeGraphQL(query, orgDevToken); | ||
|
|
There was a problem hiding this comment.
Log Improvement Suggestion No: 5
| json response = check executeGraphQL(query, orgDevToken); | |
| if (response.errors is json) { | |
| log:printError("GraphQL query for tracingInSync/statisticsInSync failed"); | |
| } else { | |
| log:printDebug("Successfully queried tracingInSync/statisticsInSync fields"); | |
| } |
There was a problem hiding this comment.
AI Agent Log Improvement Checklist
- The log-related comments and suggestions in this review were generated by an AI tool to assist with identifying potential improvements. Purpose of reviewing the code for log improvements is to improve the troubleshooting capabilities of our products.
- Please make sure to manually review and validate all suggestions before applying any changes. Not every code suggestion would make sense or add value to our purpose. Therefore, you have the freedom to decide which of the suggestions are helpful.
✅ Before merging this pull request:
- Review all AI-generated comments for accuracy and relevance.
- Complete and verify the table below. We need your feedback to measure the accuracy of these suggestions and the value they add. If you are rejecting a certain code suggestion, please mention the reason briefly in the suggestion for us to capture it.
WalkthroughThis change implements artifact tracing and statistics synchronization state tracking. It introduces Changes
Sequence DiagramsequenceDiagram
participant Browser
participant Frontend as Frontend<br/>(EntryPoints)
participant GraphQL as GraphQL API
participant Storage as Storage<br/>(Reconcile State)
participant DB as Database
Browser->>Frontend: Select artifact
Frontend->>GraphQL: Query templatesByEnvironmentAndComponent
GraphQL->>DB: Query templates
DB-->>GraphQL: Return templates
GraphQL->>Storage: queryArtifactState(componentId, environmentId)
Storage->>DB: Fetch reconcile_desired_state<br/>& reconcile_observed_state
DB-->>Storage: Return artifact states
Storage-->>GraphQL: Artifact state mappings
GraphQL->>GraphQL: Enrich templates with<br/>tracing/tracingInSync<br/>statistics/statisticsInSync
GraphQL-->>Frontend: Templates with sync fields
Frontend->>Frontend: Conditionally update<br/>toggles only if<br/>InSync !== false
Frontend-->>Browser: Render UI with<br/>current state
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~20 minutes Poem
🚥 Pre-merge checks | ✅ 2 | ❌ 3❌ Failed checks (3 warnings)
✅ Passed checks (2 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
Fix Report — Issue #437: Tracing toggle requires page refreshPR Links
Changes Made
|
| # | Root Cause | Fix |
|---|---|---|
| 1 | Template missing tracingInSync/statisticsInSync in gqlFields → polling never activated |
Added fields to ARTIFACT_QUERY_MAP entry for Template |
| 2 | useEffect in EntryPoints.tsx reset optimistic toggle when stale heartbeat overwrote observed state |
Guard reset behind inSync !== false check |
| 3 | templatesByEnvironmentAndComponent resolver not enriching from reconcile state |
Added queryArtifactState enrichment loop (matches other artifact type resolvers) |
| 4 | writeObservedStateMI not writing Template tracing observed state |
Added Template loop in heartbeat repository |
There was a problem hiding this comment.
Actionable comments posted: 3
🧹 Nitpick comments (1)
icp_server/tests/artifact_tracing_tests.bal (1)
30-30: Unused constantMI_RUNTIME_ID.This constant is declared but never referenced in any of the tests. If it's reserved for future test expansion, consider adding a comment to clarify its purpose. Otherwise, remove it to avoid confusion.
🧹 Proposed fix to remove unused constant
// Test data IDs for Issue 437 (defined in h2_test_data.sql) -// MI Runtime 6: Project 1 / Component 1 / Dev / RUNNING (MI) -const string MI_RUNTIME_ID = "880e8400-e29b-41d4-a716-446655440006"; - // Template names from test seed data🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@icp_server/tests/artifact_tracing_tests.bal` at line 30, The constant MI_RUNTIME_ID is declared but never used; either remove the unused declaration (const string MI_RUNTIME_ID = "...") from the test file or, if you intend to keep it for future tests, add a one-line comment above MI_RUNTIME_ID clarifying its reserved purpose (e.g., "Reserved for future MI runtime tests") so readers know it's intentional; update the symbol MI_RUNTIME_ID accordingly in the tests file.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@ARCHITECTURE.md`:
- Around line 5-18: Update the fenced code block that begins with the lines
"Browser -> ICP-AUTH/HB:9445" ... "ICP-OBS-ADPT -> OpenSearch:9200" so the
opening fence includes a language tag (use "text") — change the initial ``` to
```text; ensure the closing ``` remains; apply the same change to any other
un-annotated fenced blocks in ARCHITECTURE.md to satisfy markdownlint.
In `@frontend/src/components/EntryPoints.tsx`:
- Around line 108-117: The local toggle state leaks across artifact selections
because the useEffect guards skip calling setTracingEnabled/setStatisticsEnabled
when tracingInSync/statisticsInSync are false; add a ref (e.g.,
prevArtifactKeyRef) to detect when artifactKey changes and, inside the existing
useEffect, if prevArtifactKeyRef.current !== artifactKey then force reinitialize
the toggles by calling setTracingEnabled(toEnabled(artifact.tracing)) and
setStatisticsEnabled(toEnabled(artifact.statistics)) regardless of the inSync
flags, then update prevArtifactKeyRef.current = artifactKey; alternatively, a
simpler fix is to add key={artifactKey} to the EntryPointDetail element so React
remounts the component on artifact selection.
In `@icp_server/resources/db/init-scripts/h2_test_data.sql`:
- Around line 341-386: The fixtures currently reuse component id
'640e8400-e29b-41d4-a716-446655440001' which is seeded as a BI component; create
a new MI component UUID (e.g. a new value) and seed a corresponding component
row for MI, then update the runtime row (runtime_id
'880e8400-e29b-41d4-a716-446655440006') and all reconcile rows (the
reconcile_desired_state and reconcile_observed_state INSERTs) to reference that
new MI component id instead of the BI id so the runtime and artifacts like
'hello-template', 'synced-template', and 'hello-processor' are under an MI
component; this will satisfy validateHeartbeatResolution(...) and align with the
frontend check (componentType === 'MI').
---
Nitpick comments:
In `@icp_server/tests/artifact_tracing_tests.bal`:
- Line 30: The constant MI_RUNTIME_ID is declared but never used; either remove
the unused declaration (const string MI_RUNTIME_ID = "...") from the test file
or, if you intend to keep it for future tests, add a one-line comment above
MI_RUNTIME_ID clarifying its reserved purpose (e.g., "Reserved for future MI
runtime tests") so readers know it's intentional; update the symbol
MI_RUNTIME_ID accordingly in the tests file.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
Run ID: 989ca8da-9566-466d-b09c-74a9afe445fb
📒 Files selected for processing (10)
ARCHITECTURE.mdAgents.mdCLAUDE.mdfrontend/src/api/queries.tsfrontend/src/components/EntryPoints.tsxicp_server/graphql_api.balicp_server/modules/storage/heartbeat_repository.balicp_server/modules/types/types.balicp_server/resources/db/init-scripts/h2_test_data.sqlicp_server/tests/artifact_tracing_tests.bal
| ``` | ||
| Browser -> ICP-AUTH/HB:9445 | ||
| Browser -> ICP-GraphQL:9446 | ||
| Browser -> ICP-OBS:9448 | ||
| Ballerina Integrator -> ICP-AUTH/HB:9445 | ||
| Micro Integrator -> ICP-AUTH/HB:9445 | ||
| ICP-AUTH/HB -> ICP-AUTH-ADPT:9447 | ||
| ICP-OBS -> ICP-OBS-ADPT:9449 | ||
| ICP-GraphQL -> Micro Integrator:9164 | ||
| ICP-AUTH/HB -> DB:5432 | ||
| ICP-GraphQL -> DB:5432 | ||
| ICP-AUTH-ADPT -> DB:5432 | ||
| ICP-OBS-ADPT -> OpenSearch:9200 | ||
| ``` |
There was a problem hiding this comment.
Add a language to this fenced block.
markdownlint will keep flagging this fence until it is annotated. text is enough here.
📝 Suggested change
-```
+```text
Browser -> ICP-AUTH/HB:9445
Browser -> ICP-GraphQL:9446
Browser -> ICP-OBS:9448
Ballerina Integrator -> ICP-AUTH/HB:9445
Micro Integrator -> ICP-AUTH/HB:9445
ICP-AUTH/HB -> ICP-AUTH-ADPT:9447
ICP-OBS -> ICP-OBS-ADPT:9449
ICP-GraphQL -> Micro Integrator:9164
ICP-AUTH/HB -> DB:5432
ICP-GraphQL -> DB:5432
ICP-AUTH-ADPT -> DB:5432
ICP-OBS-ADPT -> OpenSearch:9200</details>
<!-- suggestion_start -->
<details>
<summary>📝 Committable suggestion</summary>
> ‼️ **IMPORTANT**
> Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
```suggestion
🧰 Tools
🪛 markdownlint-cli2 (0.22.0)
[warning] 5-5: Fenced code blocks should have a language specified
(MD040, fenced-code-language)
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@ARCHITECTURE.md` around lines 5 - 18, Update the fenced code block that
begins with the lines "Browser -> ICP-AUTH/HB:9445" ... "ICP-OBS-ADPT ->
OpenSearch:9200" so the opening fence includes a language tag (use "text") —
change the initial ``` to ```text; ensure the closing ``` remains; apply the
same change to any other un-annotated fenced blocks in ARCHITECTURE.md to
satisfy markdownlint.
| useEffect(() => { | ||
| setTracingEnabled(toEnabled(artifact.tracing)); | ||
| setStatisticsEnabled(toEnabled(artifact.statistics)); | ||
| if (artifact.tracingInSync !== false) { | ||
| setTracingEnabled(toEnabled(artifact.tracing)); | ||
| } | ||
| if (artifact.statisticsInSync !== false) { | ||
| setStatisticsEnabled(toEnabled(artifact.statistics)); | ||
| } | ||
| setStatusEnabled(toEnabled(artifact.state)); | ||
| setListenerEnabled(toEnabled(artifact.state)); | ||
| }, [artifactKey, artifact.tracing, artifact.statistics, artifact.state]); | ||
| }, [artifactKey, artifact.tracing, artifact.tracingInSync, artifact.statistics, artifact.statisticsInSync, artifact.state]); |
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
set -euo pipefail
sed -n '108,117p' frontend/src/components/EntryPoints.tsx
printf '\n---\n\n'
sed -n '512,515p' frontend/src/components/EntryPoints.tsxRepository: wso2/integration-control-plane
Length of output: 826
🏁 Script executed:
cat -n frontend/src/components/EntryPoints.tsx | head -130 | tail -30Repository: wso2/integration-control-plane
Length of output: 1558
🏁 Script executed:
# Check the declaration of tracingEnabled and statisticsEnabled state
rg "tracingEnabled|statisticsEnabled" frontend/src/components/EntryPoints.tsx -B 2 -A 2Repository: wso2/integration-control-plane
Length of output: 2111
🏁 Script executed:
# Check if EntryPointDetail has other effects or state management
rg "EntryPointDetail" frontend/src/components/ -A 5 -B 5 --type typescriptRepository: wso2/integration-control-plane
Length of output: 108
🏁 Script executed:
# Check if there's a useEffect that might reset these values when artifactKey changes
ast-grep --pattern 'useEffect(() => { $$$ }, [$$$ artifactKey $$$])'Repository: wso2/integration-control-plane
Length of output: 56
🏁 Script executed:
# Look for other effects in the same component
sed -n '50,550p' frontend/src/components/EntryPoints.tsx | rg "useEffect|useState" -B 1 -A 3Repository: wso2/integration-control-plane
Length of output: 2798
🏁 Script executed:
# Find the exact line 514 and surrounding context
sed -n '510,520p' frontend/src/components/EntryPoints.tsxRepository: wso2/integration-control-plane
Length of output: 437
🏁 Script executed:
# Check if there are other effects that might reset state when selected artifact changes
sed -n '50,200p' frontend/src/components/EntryPoints.tsx | grep -n "useEffect\|selected\|artifact" | head -20Repository: wso2/integration-control-plane
Length of output: 1792
🏁 Script executed:
# Verify the component receives 'selected' prop and check its structure
grep -n "selected" frontend/src/components/EntryPoints.tsx | head -10Repository: wso2/integration-control-plane
Length of output: 1053
🏁 Script executed:
# Check if there's a key prop or any React.memo that might affect this
grep -n "EntryPointDetail\|key=" frontend/src/components/EntryPoints.tsx | grep -A 2 -B 2 "514"Repository: wso2/integration-control-plane
Length of output: 644
🏁 Script executed:
# Verify the effect dependency array is correct - when artifactKey changes, effect should run
sed -n '106,118p' frontend/src/components/EntryPoints.tsxRepository: wso2/integration-control-plane
Length of output: 728
🏁 Script executed:
# Check if selectedEntry has properties that would create different artifactKey values
sed -n '420,430p' frontend/src/components/EntryPoints.tsxRepository: wso2/integration-control-plane
Length of output: 642
Reinitialize the local toggles when the artifact selection changes.
Line 514 renders EntryPointDetail without a key prop, reusing the same component instance across artifact selections. The effect guards prevent setTracingEnabled and setStatisticsEnabled from running when tracingInSync === false or statisticsInSync === false. This creates a state leak: switching from one out-of-sync artifact to another keeps the previous artifact's optimistic toggle values because both setters are skipped for both artifacts.
The guards correctly prevent stale resets during repeated fetches of the same artifact, but they must still reset when the artifact key changes. Add a ref to detect key changes and force reinitialize the toggles on artifact selection.
Suggested fix
+ const previousArtifactKey = useRef(artifactKey);
useEffect(() => {
- if (artifact.tracingInSync !== false) {
+ const artifactChanged = previousArtifactKey.current !== artifactKey;
+ previousArtifactKey.current = artifactKey;
+ if (artifactChanged || artifact.tracingInSync !== false) {
setTracingEnabled(toEnabled(artifact.tracing));
}
- if (artifact.statisticsInSync !== false) {
+ if (artifactChanged || artifact.statisticsInSync !== false) {
setStatisticsEnabled(toEnabled(artifact.statistics));
}
setStatusEnabled(toEnabled(artifact.state));
setListenerEnabled(toEnabled(artifact.state));
}, [artifactKey, artifact.tracing, artifact.tracingInSync, artifact.statistics, artifact.statisticsInSync, artifact.state]);Alternatively, add a key={artifactKey} prop to the EntryPointDetail component at line 514.
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| useEffect(() => { | |
| setTracingEnabled(toEnabled(artifact.tracing)); | |
| setStatisticsEnabled(toEnabled(artifact.statistics)); | |
| if (artifact.tracingInSync !== false) { | |
| setTracingEnabled(toEnabled(artifact.tracing)); | |
| } | |
| if (artifact.statisticsInSync !== false) { | |
| setStatisticsEnabled(toEnabled(artifact.statistics)); | |
| } | |
| setStatusEnabled(toEnabled(artifact.state)); | |
| setListenerEnabled(toEnabled(artifact.state)); | |
| }, [artifactKey, artifact.tracing, artifact.statistics, artifact.state]); | |
| }, [artifactKey, artifact.tracing, artifact.tracingInSync, artifact.statistics, artifact.statisticsInSync, artifact.state]); | |
| const previousArtifactKey = useRef(artifactKey); | |
| useEffect(() => { | |
| const artifactChanged = previousArtifactKey.current !== artifactKey; | |
| previousArtifactKey.current = artifactKey; | |
| if (artifactChanged || artifact.tracingInSync !== false) { | |
| setTracingEnabled(toEnabled(artifact.tracing)); | |
| } | |
| if (artifactChanged || artifact.statisticsInSync !== false) { | |
| setStatisticsEnabled(toEnabled(artifact.statistics)); | |
| } | |
| setStatusEnabled(toEnabled(artifact.state)); | |
| setListenerEnabled(toEnabled(artifact.state)); | |
| }, [artifactKey, artifact.tracing, artifact.tracingInSync, artifact.statistics, artifact.statisticsInSync, artifact.state]); |
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@frontend/src/components/EntryPoints.tsx` around lines 108 - 117, The local
toggle state leaks across artifact selections because the useEffect guards skip
calling setTracingEnabled/setStatisticsEnabled when
tracingInSync/statisticsInSync are false; add a ref (e.g., prevArtifactKeyRef)
to detect when artifactKey changes and, inside the existing useEffect, if
prevArtifactKeyRef.current !== artifactKey then force reinitialize the toggles
by calling setTracingEnabled(toEnabled(artifact.tracing)) and
setStatisticsEnabled(toEnabled(artifact.statistics)) regardless of the inSync
flags, then update prevArtifactKeyRef.current = artifactKey; alternatively, a
simpler fix is to add key={artifactKey} to the EntryPointDetail element so React
remounts the component on artifact selection.
| -- MI Runtime 6: Project 1 / Component 1 / Dev / RUNNING (MI type for tracing tests) | ||
| INSERT INTO runtimes ( | ||
| runtime_id, name, project_id, component_id, environment_id, | ||
| runtime_type, status, version, platform_name, platform_version, | ||
| registration_time, last_heartbeat | ||
| ) VALUES ( | ||
| '880e8400-e29b-41d4-a716-446655440006', | ||
| 'mi-dev-runtime', | ||
| '650e8400-e29b-41d4-a716-446655440001', | ||
| '640e8400-e29b-41d4-a716-446655440001', | ||
| '750e8400-e29b-41d4-a716-446655440001', | ||
| 'MI', 'RUNNING', '4.3.0', 'wso2-mi', '4.3.0', | ||
| CURRENT_TIMESTAMP, CURRENT_TIMESTAMP | ||
| ); | ||
|
|
||
| -- Template: hello-template — tracing toggle enabled but not yet confirmed by MI (tracingInSync=false) | ||
| INSERT INTO mi_template_artifacts (runtime_id, template_name, template_type, tracing, statistics, carbon_app) | ||
| VALUES ('880e8400-e29b-41d4-a716-446655440006', 'hello-template', 'sequence', 'disabled', 'disabled', NULL); | ||
|
|
||
| -- Template: synced-template — tracing already confirmed by MI (tracingInSync=true) | ||
| INSERT INTO mi_template_artifacts (runtime_id, template_name, template_type, tracing, statistics, carbon_app) | ||
| VALUES ('880e8400-e29b-41d4-a716-446655440006', 'synced-template', 'sequence', 'enabled', 'disabled', NULL); | ||
|
|
||
| -- MessageProcessor: hello-processor — for schema validation (no tracing field) | ||
| INSERT INTO mi_message_processor_artifacts (runtime_id, processor_name, artifact_id, processor_type, state, carbon_app) | ||
| VALUES ('880e8400-e29b-41d4-a716-446655440006', 'hello-processor', '990e8400-e29b-41d4-a716-446655440001', 'Scheduled-message-forwarding-processor', 'active', NULL); | ||
|
|
||
| -- Reconcile desired state: tracing=enabled for hello-template (user toggled ON) | ||
| INSERT INTO reconcile_desired_state (component_id, env_id, artifact_name, artifact_type, state_key, state_value) | ||
| VALUES ('640e8400-e29b-41d4-a716-446655440001', '750e8400-e29b-41d4-a716-446655440001', | ||
| 'hello-template', 'template', 'tracing', 'enabled'); | ||
|
|
||
| -- Reconcile desired state: tracing=enabled for synced-template (already confirmed) | ||
| INSERT INTO reconcile_desired_state (component_id, env_id, artifact_name, artifact_type, state_key, state_value) | ||
| VALUES ('640e8400-e29b-41d4-a716-446655440001', '750e8400-e29b-41d4-a716-446655440001', | ||
| 'synced-template', 'template', 'tracing', 'enabled'); | ||
|
|
||
| -- Reconcile observed state: hello-template still disabled (stale heartbeat, not yet applied) | ||
| INSERT INTO reconcile_observed_state (runtime_id, component_id, env_id, artifact_name, artifact_type, state_key, state_value, optimistic, heartbeat_gen) | ||
| VALUES ('880e8400-e29b-41d4-a716-446655440006', '640e8400-e29b-41d4-a716-446655440001', '750e8400-e29b-41d4-a716-446655440001', | ||
| 'hello-template', 'template', 'tracing', 'disabled', FALSE, 1); | ||
|
|
||
| -- Reconcile observed state: synced-template enabled (matches desired — in sync) | ||
| INSERT INTO reconcile_observed_state (runtime_id, component_id, env_id, artifact_name, artifact_type, state_key, state_value, optimistic, heartbeat_gen) | ||
| VALUES ('880e8400-e29b-41d4-a716-446655440006', '640e8400-e29b-41d4-a716-446655440001', '750e8400-e29b-41d4-a716-446655440001', | ||
| 'synced-template', 'template', 'tracing', 'enabled', FALSE, 1); |
There was a problem hiding this comment.
Seed these tracing fixtures under an MI component.
Lines 80-83 create 640e8400-e29b-41d4-a716-446655440001 as a BI component, but this block reuses that ID for an MI runtime and MI reconcile rows. validateHeartbeatResolution(...) rejects that type mismatch in production, and the frontend only enables the Template/MessageProcessor path when componentType === 'MI', so this fixture will not cover the real execution path. Point Runtime 6 and the new reconcile records at a dedicated MI component instead.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@icp_server/resources/db/init-scripts/h2_test_data.sql` around lines 341 -
386, The fixtures currently reuse component id
'640e8400-e29b-41d4-a716-446655440001' which is seeded as a BI component; create
a new MI component UUID (e.g. a new value) and seed a corresponding component
row for MI, then update the runtime row (runtime_id
'880e8400-e29b-41d4-a716-446655440006') and all reconcile rows (the
reconcile_desired_state and reconcile_observed_state INSERTs) to reference that
new MI component id instead of the BI id so the runtime and artifacts like
'hello-template', 'synced-template', and 'hello-processor' are under an MI
component; this will satisfy validateHeartbeatResolution(...) and align with the
frontend check (componentType === 'MI').
Summary
tracingInSync/statisticsInSynctoTemplateGraphQL type — thetemplatesByEnvironmentAndComponentresolver now enriches results from reconcile state, enabling the frontend polling loop to activate for Template artifacts.EntryPoints.tsx—useEffectno longer resets the toggle to the server value whentracingInSync === false/statisticsInSync === false, preventing the stale-heartbeat race from reverting the UI.tracingfield fromMessageProcessorgqlFields— MessageProcessor does not have backend tracing support; removing this field alignsgqlFieldswith the actual schema.writeObservedStateMI—batchUpsertReconcileObservedStatenow includes Template tracing/statistics entries so heartbeats keep reconcile state current.icp_server/tests/artifact_tracing_tests.baland H2 test data rows covering in-sync and out-of-sync scenarios for Template tracing.Closes #437
Root Cause
Two interacting bugs prevented immediate UI feedback after a tracing toggle:
Missing
tracingInSync/statisticsInSyncinARTIFACT_QUERY_MAPforMessageProcessorandTemplate(frontend/src/api/queries.ts:465,471).supportedInSyncKeysis derived by filteringIN_SYNC_KEYSagainstgqlFields; without these fields, the 1-secondrefetchIntervalpolling was never activated for those artifact types.useEffectreset on stale heartbeat (EntryPoints.tsx:108-113): when MI hadn't yet applied the tracing command before its next heartbeat,batchUpsertReconcileObservedStateoverwrote the optimistic observed state with the stale value, and theuseEffectreset the local toggle back to the old position.Test Plan
bal runinicp_server/)bal testinicp_server/— confirmartifact-tracinggroup passestemplatesByEnvironmentAndComponentGraphQL query returnstracingInSyncandstatisticsInSyncfieldsSummary by CodeRabbit
New Features
Bug Fixes