Skip to content

[duplicate-code] Duplicate Code: Processing Steps JSON Parsing Duplicated in Classic and Wired Stream Models #3843

Description

@github-actions

Summary

The processing_steps JSON parse/serialize logic is duplicated between models_classic.go and models_wired.go in the Kibana Streams package. Both models contain near-identical blocks (~15 lines each) for unmarshalling processing steps from the API and marshalling them back, with only minor error-handling differences.

Duplication Details

Pattern: Duplicated processing_steps Parse/Serialize Logic

  • Severity: Medium
  • Occurrences: 2 (classic and wired stream models)
  • Locations:
    • internal/kibana/streams/models_classic.go (lines 51–65 for read, 127–138 for write)
    • internal/kibana/streams/models_wired.go (lines 53–69 for read, 150–161 for write)

Read-path duplicate (appears in both classicConfigModel.populateFromAPI and wiredConfigModel.populateFromAPI):

// Processing steps — each step is a JSON-encoded streamlang object.
// An empty array from the API is treated as null (no steps configured).
if len(ingest.Processing.Steps) > 0 {
    var rawSteps []json.RawMessage
    if err := json.Unmarshal(ingest.Processing.Steps, &rawSteps); err != nil {
        // classic: silently sets null
        // wired: returns a diagnostic error
    }
    if len(rawSteps) > 0 {
        elems := make([]attr.Value, len(rawSteps))
        for i, raw := range rawSteps {
            elems[i] = jsontypes.NewNormalizedValue(string(raw))
        }
        m.ProcessingSteps = types.ListValueMust(jsontypes.NormalizedType{}, elems)
    } else {
        m.ProcessingSteps = types.ListNull(jsontypes.NormalizedType{})
    }
} else {
    m.ProcessingSteps = types.ListNull(jsontypes.NormalizedType{})
}

Write-path duplicate (appears in both models' toAPIIngest functions):

rawSteps := make([]json.RawMessage, 0)
for _, elem := range m.ProcessingSteps.Elements() {
    if norm, ok := elem.(jsontypes.Normalized); ok {
        rawSteps = append(rawSteps, json.RawMessage(norm.ValueString()))
    }
}
stepsJSON, err := json.Marshal(rawSteps)
// ... error handling ...
ingest.Processing.Steps = stepsJSON

Notable divergence: The classic model silently sets null on unmarshal error; the wired model returns a diag.Diagnostics error. This inconsistency is itself a risk introduced by the duplication.

Impact Analysis

  • Maintainability: Any change to how processing steps are serialized (e.g., supporting step metadata) must be applied in two places.
  • Bug Risk: The existing inconsistency in error handling between classic (silent null) and wired (diagnostic error) was likely an accidental divergence from copy-paste. Future edits may introduce more such inconsistencies.
  • Code Bloat: ~30 lines of duplicated logic that could be a single shared helper.

Refactoring Recommendations

  1. Extract shared helpers

    • populateProcessingStepsFromAPI(ingest *kibanaoapi.StreamIngest) (types.List, diag.Diagnostics) — handles the read path for both models
    • processingStepsToAPI(steps types.List) (json.RawMessage, diag.Diagnostics) — handles the write path
    • Place in internal/kibana/streams/models.go (already the shared models file for the package)
    • Estimated effort: low (~2 hours); straightforward extraction with uniform error handling
  2. Standardize error handling

    • During extraction, adopt the wired model's pattern (return diag.Diagnostics on error) for both models — silent errors are harder to debug
    • Update classicConfigModel.populateFromAPI signature to return diag.Diagnostics to match wired

Implementation Checklist

  • Extract populateProcessingStepsFromAPI helper to models.go
  • Extract processingStepsToAPI helper to models.go
  • Standardize error handling to return diagnostics in both classic and wired callers
  • Update both models_classic.go and models_wired.go to call shared helpers
  • Run make build to confirm no compilation errors
  • Verify acceptance tests pass

Analysis Metadata

  • Analyzed Files: internal/kibana/streams/models_classic.go, internal/kibana/streams/models_wired.go
  • Detection Method: Semantic code analysis — structural comparison of populateFromAPI and toAPIIngest methods
  • Commit: 0317686 (kibana/streams test coverage update that touched these files)
  • Analysis Date: 2026-06-22

Generated by Duplicate Code Detector · sonnet46 2.6M ·

Metadata

Metadata

Assignees

No one assigned

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions