Skip to content

Commit 5d27b71

Browse files
committed
refactor: quick-win cleanup — panic stubs, SaveToFile, dead code, error handling, syncWriter
1 parent eae483a commit 5d27b71

20 files changed

Lines changed: 144 additions & 95 deletions

mdl/backend/mpr/backend.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -768,17 +768,17 @@ func (b *MprBackend) OpenWorkflowForMutation(unitID model.ID) (backend.WorkflowM
768768
// WidgetSerializationBackend
769769

770770
func (b *MprBackend) SerializeWidget(w pages.Widget) (any, error) {
771-
panic("MprBackend.SerializeWidget not yet implemented") // TODO: implement in PR #237
771+
return mpr.SerializeWidget(w), nil
772772
}
773773

774774
func (b *MprBackend) SerializeClientAction(a pages.ClientAction) (any, error) {
775-
panic("MprBackend.SerializeClientAction not yet implemented") // TODO: implement in PR #237
775+
return mpr.SerializeClientAction(a), nil
776776
}
777777

778778
func (b *MprBackend) SerializeDataSource(ds pages.DataSource) (any, error) {
779779
return mpr.SerializeCustomWidgetDataSource(ds), nil
780780
}
781781

782782
func (b *MprBackend) SerializeWorkflowActivity(a workflows.WorkflowActivity) (any, error) {
783-
panic("MprBackend.SerializeWorkflowActivity not yet implemented") // TODO: implement in PR #237
783+
return mpr.SerializeWorkflowActivity(a), nil
784784
}

mdl/catalog/builder.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -79,8 +79,8 @@ type Builder struct {
7979
progress ProgressFunc
8080
hierarchy *hierarchy
8181
tx CatalogTx // Transaction for batched inserts
82-
fullMode bool // If true, do full parsing (activities/widgets)
83-
sourceMode bool // If true, build source FTS table (implies full)
82+
fullMode bool // If true, do full parsing (activities/widgets)
83+
sourceMode bool // If true, build source FTS table (implies full)
8484
describeFunc DescribeFunc
8585

8686
// Document caches — avoid redundant BSON parsing across builder phases.

mdl/catalog/builder_microflows_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,8 @@ package catalog
55
import (
66
"testing"
77

8-
"github.com/mendixlabs/mxcli/sdk/microflows"
98
"github.com/mendixlabs/mxcli/model"
9+
"github.com/mendixlabs/mxcli/sdk/microflows"
1010
)
1111

1212
// unknownMicroflowObject satisfies MicroflowObject but is not in the type switch.

mdl/catalog/builder_pages.go

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ package catalog
55
import (
66
"database/sql"
77
"encoding/base64"
8+
"fmt"
89
"strings"
910

1011
"go.mongodb.org/mongo-driver/bson/primitive"
@@ -103,7 +104,7 @@ func (b *Builder) buildPages() error {
103104
// Insert widgets only in full mode
104105
if b.fullMode && len(rawWidgets) > 0 {
105106
for _, w := range rawWidgets {
106-
_, _ = widgetStmt.Exec(
107+
if _, err := widgetStmt.Exec(
107108
w.ID,
108109
w.Name,
109110
w.WidgetType,
@@ -117,7 +118,9 @@ func (b *Builder) buildPages() error {
117118
"",
118119
projectID, projectName, snapshotID, snapshotDate, snapshotSource,
119120
sourceID, sourceBranch, sourceRevision,
120-
)
121+
); err != nil {
122+
return fmt.Errorf("insert widget %s for page %s: %w", w.Name, qualifiedName, err)
123+
}
121124
widgetCount++
122125
}
123126
}

mdl/catalog/catalog.go

Lines changed: 2 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -284,16 +284,10 @@ func (c *Catalog) SaveToFile(path string) error {
284284
}
285285
rawDB := sdb.RawDB()
286286

287-
// Open destination file database
288-
destDB, err := sql.Open("sqlite", path)
289-
if err != nil {
290-
return fmt.Errorf("failed to create catalog file: %w", err)
291-
}
292-
defer destDB.Close()
293-
294287
// Use SQLite backup API via VACUUM INTO (SQLite 3.27+)
295288
// Fall back to manual copy if not available
296-
_, err = rawDB.Exec(fmt.Sprintf("VACUUM INTO '%s'", path))
289+
safePath := strings.ReplaceAll(path, "'", "''")
290+
_, err := rawDB.Exec(fmt.Sprintf("VACUUM INTO '%s'", safePath))
297291
if err != nil {
298292
// Fall back: export and import
299293
return c.saveToFileManual(path, rawDB)

mdl/executor/cmd_catalog.go

Lines changed: 36 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,12 @@ import (
77
"context"
88
"encoding/json"
99
"fmt"
10+
"io"
11+
"log"
1012
"os"
1113
"path/filepath"
1214
"strings"
15+
"sync"
1316
"time"
1417

1518
"github.com/mendixlabs/mxcli/mdl/ast"
@@ -18,6 +21,19 @@ import (
1821
"github.com/mendixlabs/mxcli/model"
1922
)
2023

24+
// syncWriter wraps an io.Writer with a mutex so concurrent goroutines
25+
// (e.g. background catalog build) can write without racing.
26+
type syncWriter struct {
27+
mu sync.Mutex
28+
w io.Writer
29+
}
30+
31+
func (sw *syncWriter) Write(p []byte) (int, error) {
32+
sw.mu.Lock()
33+
defer sw.mu.Unlock()
34+
return sw.w.Write(p)
35+
}
36+
2137
// execShowCatalogTables handles SHOW CATALOG TABLES.
2238
func execShowCatalogTables(ctx *ExecContext) error {
2339
// Build catalog if not already built (fast mode by default)
@@ -449,19 +465,29 @@ func execRefreshCatalogStmt(ctx *ExecContext, stmt *ast.RefreshCatalogStmt) erro
449465

450466
// Handle background mode — clone ctx so the goroutine doesn't race
451467
// with the main dispatch loop (which may syncBack and mutate fields).
452-
// NOTE: bgCtx.Output still shares the underlying writer with the main
453-
// goroutine. This is a pre-existing limitation — the original code also
454-
// wrote to ctx.Output from the goroutine. A synchronized writer would
455-
// fix this but is out of scope for the executor cleanup.
456468
if stmt.Background {
457-
bgCtx := *ctx // shallow copy — isolates scalar fields
458-
bgCtx.Cache = nil // detach shared cache so preWarmCache writes stay local
469+
bgCtx := *ctx // shallow copy — isolates scalar fields
470+
bgCtx.Cache = nil // detach shared cache so preWarmCache writes stay local
471+
sw := &syncWriter{w: ctx.Output} // shared mutex-wrapped writer
472+
bgCtx.Output = sw // background goroutine writes through sw
473+
syncCatalog := ctx.SyncCatalog // capture callback before returning
459474
go func() {
460475
if err := buildCatalog(&bgCtx, stmt.Full, stmt.Source); err != nil {
461476
fmt.Fprintf(bgCtx.Output, "Background catalog build failed: %v\n", err)
477+
return
478+
}
479+
// Propagate the built catalog back to the Executor so the next
480+
// command picks it up. syncBack has already run for this statement,
481+
// so we use the SyncCatalog callback to write directly to e.catalog.
482+
if bgCtx.Catalog != nil {
483+
if syncCatalog != nil {
484+
syncCatalog(bgCtx.Catalog)
485+
} else {
486+
bgCtx.Catalog.Close()
487+
}
462488
}
463489
}()
464-
fmt.Fprintln(ctx.Output, "Catalog build started in background...")
490+
fmt.Fprintln(sw, "Catalog build started in background...")
465491
return nil
466492
}
467493

@@ -618,7 +644,9 @@ func outputCatalogResults(ctx *ExecContext, result *catalog.QueryResult) {
618644
}
619645
tr.Rows = append(tr.Rows, outRow)
620646
}
621-
_ = writeResult(ctx, tr)
647+
if err := writeResult(ctx, tr); err != nil {
648+
log.Printf("warning: failed to write catalog results: %v", err)
649+
}
622650
}
623651

624652
// formatValue formats a value for display.

mdl/executor/cmd_microflows_builder.go

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -23,25 +23,25 @@ type flowBuilder struct {
2323
posY int
2424
baseY int // Base Y position (for returning after ELSE branches)
2525
spacing int
26-
returnValue string // Return value expression for RETURN statement (used by buildFlowGraph final EndEvent)
27-
endsWithReturn bool // True if the flow already ends with EndEvent(s) from RETURN statements
28-
varTypes map[string]string // Variable name -> entity qualified name (for CHANGE statements)
29-
declaredVars map[string]string // Declared primitive variables: name -> type (e.g., "$IsValid" -> "Boolean")
30-
errors []string // Validation errors collected during build
31-
measurer *layoutMeasurer // For measuring statement dimensions
32-
nextConnectionPoint model.ID // For compound statements: the exit point differs from entry point
33-
nextFlowCase string // If set, next connecting flow uses this case value (for merge-less splits)
26+
returnValue string // Return value expression for RETURN statement (used by buildFlowGraph final EndEvent)
27+
endsWithReturn bool // True if the flow already ends with EndEvent(s) from RETURN statements
28+
varTypes map[string]string // Variable name -> entity qualified name (for CHANGE statements)
29+
declaredVars map[string]string // Declared primitive variables: name -> type (e.g., "$IsValid" -> "Boolean")
30+
errors []string // Validation errors collected during build
31+
measurer *layoutMeasurer // For measuring statement dimensions
32+
nextConnectionPoint model.ID // For compound statements: the exit point differs from entry point
33+
nextFlowCase string // If set, next connecting flow uses this case value (for merge-less splits)
3434
// nextFlowAnchor carries the branch-specific FlowAnchors that should be
3535
// applied to the flow created by the NEXT iteration of buildFlowGraph.
3636
// Used by guard-pattern IFs (where one branch returns and the other
3737
// continues) so the continuing branch's @anchor survives to the actual
3838
// splitID→nextActivity flow — which is emitted one iteration later by the
3939
// outer loop, not by addIfStatement.
40-
nextFlowAnchor *ast.FlowAnchors
41-
backend backend.FullBackend // For looking up page/microflow references
42-
hierarchy *ContainerHierarchy // For resolving container IDs to module names
43-
pendingAnnotations *ast.ActivityAnnotations // Pending annotations to attach to next activity
44-
restServices []*model.ConsumedRestService // Cached REST services for parameter classification
40+
nextFlowAnchor *ast.FlowAnchors
41+
backend backend.FullBackend // For looking up page/microflow references
42+
hierarchy *ContainerHierarchy // For resolving container IDs to module names
43+
pendingAnnotations *ast.ActivityAnnotations // Pending annotations to attach to next activity
44+
restServices []*model.ConsumedRestService // Cached REST services for parameter classification
4545
// previousStmtAnchor holds the Anchor annotation of the statement that
4646
// just emitted an activity, so the next flow's OriginConnectionIndex can
4747
// be overridden by the user. Cleared after each flow is created.

mdl/executor/cmd_microflows_builder_calls.go

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ package executor
55

66
import (
77
"fmt"
8+
"log"
89
"strings"
910

1011
"github.com/mendixlabs/mxcli/mdl/ast"
@@ -174,7 +175,11 @@ func (fb *flowBuilder) addCallJavaActionAction(s *ast.CallJavaActionStmt) model.
174175
// Try to look up the Java action definition to detect EntityTypeParameterType parameters
175176
var jaDef *javaactions.JavaAction
176177
if fb.backend != nil {
177-
jaDef, _ = fb.backend.ReadJavaActionByName(actionQN)
178+
var err error
179+
jaDef, err = fb.backend.ReadJavaActionByName(actionQN)
180+
if err != nil {
181+
log.Printf("warning: could not look up Java action %s: %v (entity type params will be empty)", actionQN, err)
182+
}
178183
}
179184

180185
// Build a map of parameter name -> param type for the Java action

mdl/executor/cmd_page_wireframe.go

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import (
66
"context"
77
"encoding/json"
88
"fmt"
9+
"log"
910
"strings"
1011

1112
"github.com/mendixlabs/mxcli/mdl/ast"
@@ -485,7 +486,9 @@ func pageToMdlString(ctx *ExecContext, name ast.QualifiedName, root []wireframeN
485486
var buf strings.Builder
486487
origOutput := ctx.Output
487488
ctx.Output = &buf
488-
_ = describePage(ctx, name)
489+
if err := describePage(ctx, name); err != nil {
490+
log.Printf("warning: describePage failed for %s.%s: %v", name.Module, name.Name, err)
491+
}
489492
ctx.Output = origOutput
490493

491494
mdlSource := buf.String()

mdl/executor/cmd_pages_builder_v3.go

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -491,7 +491,11 @@ func (pb *pageBuilder) buildDataSourceV3(ds *ast.DataSourceV3) (pages.DataSource
491491

492492
// Fallback to lookup if entity name not stored
493493
if entityName == "" {
494-
entityName, _ = pb.getEntityNameByID(entityID)
494+
var err error
495+
entityName, err = pb.getEntityNameByID(entityID)
496+
if err != nil {
497+
log.Printf("warning: could not resolve entity name for ID %s: %v", entityID, err)
498+
}
495499
}
496500

497501
// Use DataViewSource with IsSnippetParameter flag

0 commit comments

Comments
 (0)