Skip to content

Commit

Permalink
fix(api): clean duplicate wnode migration (#5057)
Browse files Browse the repository at this point in the history
* fix(api): clean duplicate wnode migration

Signed-off-by: Yvonnick Esnault <[email protected]>
  • Loading branch information
yesnault authored Mar 12, 2020
1 parent fef0f25 commit f483fe5
Show file tree
Hide file tree
Showing 6 changed files with 166 additions and 35 deletions.
4 changes: 4 additions & 0 deletions engine/api/api.go
Original file line number Diff line number Diff line change
Expand Up @@ -699,6 +699,10 @@ func (a *API) Serve(ctx context.Context) error {
return migrate.RefactorEnvironmentVariables(ctx, a.DBConnectionFactory.GetDBMap())
}})

migrate.Add(ctx, sdk.Migration{Name: "CleanDuplicateNodes", Release: "0.44.0", Blocker: false, Automatic: true, ExecFunc: func(ctx context.Context) error {
return migrate.CleanDuplicateNodes(ctx, a.DBConnectionFactory.GetDBMap())
}})

isFreshInstall, errF := version.IsFreshInstall(a.mustDB())
if errF != nil {
return sdk.WrapError(errF, "Unable to check if it's a fresh installation of CDS")
Expand Down
158 changes: 158 additions & 0 deletions engine/api/migrate/clean_w_nodes.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,158 @@
package migrate

import (
"context"
"database/sql"

"github.com/ovh/cds/sdk"
"github.com/ovh/cds/sdk/log"

"github.com/go-gorp/gorp"
)

// CleanDuplicateNodes .
func CleanDuplicateNodes(ctx context.Context, db *gorp.DbMap) error {
if err := cleanDuplicateNodesWNodeTrigger(ctx, db); err != nil {
return sdk.WithStack(err)
}
if err := cleanDuplicateNodesWNode(ctx, db); err != nil {
return sdk.WithStack(err)
}
return nil
}

func cleanDuplicateNodesWNodeTrigger(ctx context.Context, db *gorp.DbMap) error {
query := `WITH workflowInfo AS (
SELECT id, name, CAST(workflow_data->'node'->>'id' AS BIGINT) as rootNodeID
FROM workflow
),
oldNode as (
SELECT w_node.id as nodeID, w_node.name as nodeName, workflowInfo.id as wID, workflowInfo.name as WName
FROM w_node
JOIN workflowInfo ON workflowInfo.id = w_node.workflow_id
WHERE w_node.id < workflowInfo.rootNodeID
)
SELECT id FROM w_node_trigger where child_node_id IN (SELECT nodeID FROM oldNode);`
rows, err := db.Query(query)
if err == sql.ErrNoRows {
return nil
}
if err != nil {
return sdk.WithStack(err)
}

var idsWNodeTrigger []int64
for rows.Next() {
var id int64
if err := rows.Scan(&id); err != nil {
rows.Close() // nolint
return sdk.WithStack(err)
}
idsWNodeTrigger = append(idsWNodeTrigger, id)
}

if err := rows.Close(); err != nil {
return sdk.WithStack(err)
}

var mError = new(sdk.MultiError)
for _, idWNodeTrigger := range idsWNodeTrigger {
if err := deleteFromWNodeTrigger(ctx, db, idWNodeTrigger); err != nil {
mError.Append(err)
log.Error(ctx, "migrate.cleanDuplicateNodesWNodeTrigger> unable to delete from wNodeTrigger %d: %v", idWNodeTrigger, err)
}
}

if mError.IsEmpty() {
return nil
}
return mError
}

func deleteFromWNodeTrigger(ctx context.Context, db *gorp.DbMap, idWNodeTrigger int64) error {
tx, err := db.Begin()
if err != nil {
return sdk.WithStack(err)
}

defer tx.Rollback() // nolint

query := "DELETE FROM w_node_trigger where id = $1"
if _, err := db.Exec(query, idWNodeTrigger); err != nil {
log.Error(ctx, "migrate.deleteFromWNodeTrigger> unable to delete w_node %d: %v", idWNodeTrigger, err)
}

if err := tx.Commit(); err != nil {
return err
}

return nil
}

func cleanDuplicateNodesWNode(ctx context.Context, db *gorp.DbMap) error {
query := `WITH workflowInfo AS (
SELECT id, name, CAST(workflow_data->'node'->>'id' AS BIGINT) as rootNodeID
FROM workflow
),
oldNode as (
SELECT w_node.id as nodeID, w_node.name as nodeName, workflowInfo.id as wID, workflowInfo.name as WName
FROM w_node
JOIN workflowInfo ON workflowInfo.id = w_node.workflow_id
WHERE w_node.id < workflowInfo.rootNodeID
)
SELECT id FROM w_node where id IN (SELECT nodeID FROM oldNode);`
rows, err := db.Query(query)
if err == sql.ErrNoRows {
return nil
}
if err != nil {
return sdk.WithStack(err)
}

var idsWNode []int64
for rows.Next() {
var id int64
if err := rows.Scan(&id); err != nil {
rows.Close() // nolint
return sdk.WithStack(err)
}
idsWNode = append(idsWNode, id)
}

if err := rows.Close(); err != nil {
return sdk.WithStack(err)
}

var mError = new(sdk.MultiError)
for _, idWNode := range idsWNode {
if err := deleteFromWNode(ctx, db, idWNode); err != nil {
mError.Append(err)
log.Error(ctx, "migrate.cleanDuplicateNodesWNode> unable to delete from WNode %d: %v", idWNode, err)
}
}

if mError.IsEmpty() {
return nil
}
return mError
}

func deleteFromWNode(ctx context.Context, db *gorp.DbMap, idWNode int64) error {
tx, err := db.Begin()
if err != nil {
return sdk.WithStack(err)
}

defer tx.Rollback() // nolint

query := "DELETE FROM w_node where id = $1"
if _, err := db.Exec(query, idWNode); err != nil {
log.Error(ctx, "migrate.deleteFromWNode> unable to delete w_node %d: %v", idWNode, err)
}

if err := tx.Commit(); err != nil {
return err
}

return nil
}
32 changes: 0 additions & 32 deletions engine/sql/193_clean_workflow_data_node.sql

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,7 @@ export class WorkflowWNodeMenuEditComponent implements OnInit {
return true;
}

if (this.workflowrun && this.workflowrun.workflow && this.workflowrun.workflow.workflow_data) {
if (this.workflowrun && this.workflowrun.workflow && this.workflowrun.workflow.workflow_data.node.id > 0) {
let nbNodeFound = 0;
let parentNodes = Workflow.getParentNodeIds(this.workflowrun, this.node.id);
for (let parentNodeId of parentNodes) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,7 @@ export class WorkflowGraphComponent implements AfterViewInit {
// https://github.com/cpettitt/dagre/wiki#configuring-the-layout
this.g = new dagreD3.graphlib.Graph().setGraph({ rankdir: this.direction, nodesep: 10, ranksep: 15, edgesep: 5 });
// Create all nodes
if (this.workflow.workflow_data && this.workflow.workflow_data.node) {
if (this.workflow.workflow_data && this.workflow.workflow_data.node && this.workflow.workflow_data.node.id > 0) {
this.createNode(this.workflow.workflow_data.node);
}
if (this.workflow.workflow_data && this.workflow.workflow_data.joins) {
Expand Down
3 changes: 2 additions & 1 deletion ui/src/app/views/workflow/run/workflow.run.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,8 @@ export class WorkflowRunComponent implements OnInit {
if (!this.workflowRunData) {
this.workflowRunData = {};
}
if (!this.workflowRunData['workflow'] || !this.workflowRunData['workflow'].workflow_data) {
if (!this.workflowRunData['workflow'] || !this.workflowRunData['workflow'].workflow_data
|| this.workflowRunData['workflow'].workflow_data.node.id === 0) {
this.workflowRunData['workflow'] = s.workflowRun.workflow;
this.workflowName = s.workflowRun.workflow.name;
}
Expand Down

0 comments on commit f483fe5

Please sign in to comment.