Repository: honeydipper/honeydipper
Pull request #329 (2020-10-24 05:38:01)

fix(workflow): revert simplify export

#### Description

reverting commit cffb8b3f3fb075be0001f7a6271f427d08617f93

This change although simplifies the process of exports, but it
does not handle layered exports well, and breaks exports with
appending merge modifier.

#### This PR fixes the following issues
N/A

Charles546: This is what breaks the `whoisoncall`.
Charles546: The original commit was buried too deep, so created a commit that **simplifies** the `reverting`

Patch:
diff --git a/internal/workflow/continue.go b/internal/workflow/continue.go
index 96b0366..6beba83 100644
--- a/internal/workflow/continue.go
+++ b/internal/workflow/continue.go
@@ -86,10 +86,14 @@ func (w *Session) routeNext(msg *dipper.Message) int {
 }
 
 // mergeContext merges child workflow exported context to parent workflow.
-func (w *Session) mergeContext(exports map[string]interface{}) {
-	w.ctx = dipper.MergeMap(w.ctx, dipper.MustDeepCopy(exports))
-	w.processNoExport(exports)
-	w.exported = dipper.MergeMap(w.exported, exports)
+func (w *Session) mergeContext(exports []map[string]interface{}) {
+	for _, export := range exports {
+		w.ctx = dipper.MergeMap(w.ctx, export)
+		w.processNoExport(export)
+		if len(export) > 0 {
+			w.exported = append(w.exported, export)
+		}
+	}
 }
 
 // processNoExport prevent exporting the data into parent workflow session.
@@ -110,31 +114,40 @@ func (w *Session) processNoExport(exported map[string]interface{}) {
 
 // processExport export the data into parent workflow session.
 func (w *Session) processExport(msg *dipper.Message) {
-	if w.elseBranch == nil {
-		envData := w.buildEnvData(msg)
-		status := msg.Labels["status"]
-
-		if w.inFlyFunction != nil && status != SessionStatusError {
-			exports := config.ExportFunctionContext(w.inFlyFunction, envData, w.store.Helper.GetConfig())
-			w.mergeContext(exports)
-			delete(envData, "sysData")
-		}
-		if status != SessionStatusError {
-			w.postWorkflowExport(w.workflow.Export, envData)
-		}
-		if status == SessionStatusSuccess {
-			w.postWorkflowExport(w.workflow.ExportOnSuccess, envData)
-		}
-		if status == SessionStatusFailure {
-			w.postWorkflowExport(w.workflow.ExportOnFailure, envData)
+	if w.elseBranch != nil {
+		return
+	}
+
+	envData := w.buildEnvData(msg)
+	status := msg.Labels["status"]
+
+	if w.inFlyFunction != nil && status != SessionStatusError {
+		export := config.ExportFunctionContext(w.inFlyFunction, envData, w.store.Helper.GetConfig())
+		delete(envData, "sysData")
+		w.processNoExport(export)
+		if len(export) > 0 {
+			w.exported = append(w.exported, export)
 		}
 	}
+	if status != SessionStatusError {
+		w.postWorkflowExport(w.workflow.Export, envData)
+	}
+	if status == SessionStatusSuccess {
+		w.postWorkflowExport(w.workflow.ExportOnSuccess, envData)
+	}
+	if status == SessionStatusFailure {
+		w.postWorkflowExport(w.workflow.ExportOnFailure, envData)
+	}
 }
 
 func (w *Session) postWorkflowExport(exportMap map[string]interface{}, envData map[string]interface{}) {
 	delta := dipper.Interpolate(exportMap, envData).(map[string]interface{})
-	w.mergeContext(delta)
+	w.ctx = dipper.MergeMap(w.ctx, delta)
 	envData["ctx"] = w.ctx
+	w.processNoExport(delta)
+	if len(delta) > 0 {
+		w.exported = append(w.exported, delta)
+	}
 }
 
 // fireCompleteHooks fires all the hooks at completion time asychronously.
@@ -286,7 +299,7 @@ func (w *Session) continueAfterHook(msg *dipper.Message) {
 }
 
 // continueExec resume a session with given dipper message.
-func (w *Session) continueExec(msg *dipper.Message, exports map[string]interface{}) {
+func (w *Session) continueExec(msg *dipper.Message, exports []map[string]interface{}) {
 	w.mergeContext(exports)
 	if w.currentHook != "" {
 		w.continueAfterHook(msg)
diff --git a/internal/workflow/session.go b/internal/workflow/session.go
index 2427f93..3f06429 100644
--- a/internal/workflow/session.go
+++ b/internal/workflow/session.go
@@ -31,7 +31,7 @@ type Session struct {
 	parent         string
 	ctx            map[string]interface{}
 	event          map[string]interface{}
-	exported       map[string]interface{}
+	exported       []map[string]interface{}
 	elseBranch     *config.Workflow
 	inFlyFunction  *config.Function
 	store          *SessionStore
@@ -48,7 +48,7 @@ type Session struct {
 type SessionHandler interface {
 	prepare(msg *dipper.Message, parent interface{}, ctx map[string]interface{})
 	execute(msg *dipper.Message)
-	continueExec(msg *dipper.Message, exports map[string]interface{})
+	continueExec(msg *dipper.Message, exports []map[string]interface{})
 	onError()
 	GetName() string
 	GetDescription() string
@@ -56,7 +56,7 @@ type SessionHandler interface {
 	GetEventID() string
 	GetEventName() string
 	GetStatus() (string, string)
-	GetExported() map[string]interface{}
+	GetExported() []map[string]interface{}
 	Watch() <-chan struct{}
 }
 
@@ -467,7 +467,7 @@ func (w *Session) GetStatus() (string, string) {
 }
 
 // GetExported returns the exported data from the session.
-func (w *Session) GetExported() map[string]interface{} {
+func (w *Session) GetExported() []map[string]interface{} {
 	return w.exported
 }
 
diff --git a/internal/workflow/store.go b/internal/workflow/store.go
index 8a29929..e437fca 100644
--- a/internal/workflow/store.go
+++ b/internal/workflow/store.go
@@ -68,7 +68,7 @@ func (s *SessionStore) StartSession(wf *config.Workflow, msg *dipper.Message, ct
 }
 
 // ContinueSession resume a session with given dipper message.
-func (s *SessionStore) ContinueSession(sessionID string, msg *dipper.Message, exports map[string]interface{}) {
+func (s *SessionStore) ContinueSession(sessionID string, msg *dipper.Message, exports []map[string]interface{}) {
 	defer dipper.SafeExitOnError("[workflow] error when continuing workflow session %s", sessionID)
 	w := dipper.IDMapGet(&s.sessions, sessionID).(SessionHandler)
 	defer w.onError()


Test patch:
diff --git a/internal/workflow/main_test.go b/internal/workflow/main_test.go
index 37cd90d..48d3a6b 100644
--- a/internal/workflow/main_test.go
+++ b/internal/workflow/main_test.go
@@ -106,7 +106,7 @@ func syntheticTest(t *testing.T, configStr string, testcase map[string]interface
 			timeout = num.(time.Duration)
 		}
 		go func() {
-			store.ContinueSession(teststep["sessionID"].(string), teststep["msg"].(*dipper.Message), teststep["ctx"].(map[string]interface{}))
+			store.ContinueSession(teststep["sessionID"].(string), teststep["msg"].(*dipper.Message), []map[string]interface{}{teststep["ctx"].(map[string]interface{})})
 			daemon.Children.Wait()
 			signal <- 1
 		}()