mirror of
https://github.com/oarkflow/mq.git
synced 2025-10-19 05:04:37 +08:00
feat: add task completion
This commit is contained in:
@@ -10,14 +10,16 @@ import (
|
|||||||
"time"
|
"time"
|
||||||
|
|
||||||
"golang.org/x/exp/maps"
|
"golang.org/x/exp/maps"
|
||||||
|
|
||||||
|
"github.com/oarkflow/mq/storage"
|
||||||
|
"github.com/oarkflow/mq/storage/memory"
|
||||||
)
|
)
|
||||||
|
|
||||||
type DAG struct {
|
type DAG struct {
|
||||||
Nodes map[string]*Node
|
Nodes map[string]*Node
|
||||||
Edges map[string][]string
|
Edges map[string][]string
|
||||||
ParentNodes map[string]string
|
ParentNodes map[string]string
|
||||||
taskManager map[string]*TaskManager
|
taskManager storage.IMap[string, *TaskManager]
|
||||||
mu sync.Mutex
|
|
||||||
finalResult func(taskID string, result Result)
|
finalResult func(taskID string, result Result)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -26,20 +28,16 @@ func NewDAG(finalResultCallback func(taskID string, result Result)) *DAG {
|
|||||||
Nodes: make(map[string]*Node),
|
Nodes: make(map[string]*Node),
|
||||||
Edges: make(map[string][]string),
|
Edges: make(map[string][]string),
|
||||||
ParentNodes: make(map[string]string),
|
ParentNodes: make(map[string]string),
|
||||||
taskManager: make(map[string]*TaskManager),
|
taskManager: memory.New[string, *TaskManager](),
|
||||||
finalResult: finalResultCallback,
|
finalResult: finalResultCallback,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (tm *DAG) AddNode(nodeID string, handler func(payload json.RawMessage) Result) {
|
func (tm *DAG) AddNode(nodeID string, handler func(payload json.RawMessage) Result) {
|
||||||
tm.mu.Lock()
|
|
||||||
defer tm.mu.Unlock()
|
|
||||||
tm.Nodes[nodeID] = &Node{ID: nodeID, Handler: handler}
|
tm.Nodes[nodeID] = &Node{ID: nodeID, Handler: handler}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (tm *DAG) AddEdge(from string, to ...string) {
|
func (tm *DAG) AddEdge(from string, to ...string) {
|
||||||
tm.mu.Lock()
|
|
||||||
defer tm.mu.Unlock()
|
|
||||||
tm.Edges[from] = append(tm.Edges[from], to...)
|
tm.Edges[from] = append(tm.Edges[from], to...)
|
||||||
for _, targetNode := range to {
|
for _, targetNode := range to {
|
||||||
tm.ParentNodes[targetNode] = from
|
tm.ParentNodes[targetNode] = from
|
||||||
@@ -253,9 +251,7 @@ func (tm *DAG) formHandler(w http.ResponseWriter, r *http.Request) {
|
|||||||
gender := r.FormValue("gender")
|
gender := r.FormValue("gender")
|
||||||
taskID := generateTaskID()
|
taskID := generateTaskID()
|
||||||
manager := NewTaskManager(tm)
|
manager := NewTaskManager(tm)
|
||||||
tm.mu.Lock()
|
tm.taskManager.Set(taskID, manager)
|
||||||
tm.taskManager[taskID] = manager
|
|
||||||
tm.mu.Unlock()
|
|
||||||
go manager.Run()
|
go manager.Run()
|
||||||
payload := fmt.Sprintf(`{"email": "%s", "age": "%s", "gender": "%s"}`, email, age, gender)
|
payload := fmt.Sprintf(`{"email": "%s", "age": "%s", "gender": "%s"}`, email, age, gender)
|
||||||
manager.Trigger(taskID, "NodeA", json.RawMessage(payload))
|
manager.Trigger(taskID, "NodeA", json.RawMessage(payload))
|
||||||
@@ -270,14 +266,12 @@ func (tm *DAG) resultHandler(w http.ResponseWriter, r *http.Request) {
|
|||||||
func (tm *DAG) taskStatusHandler(w http.ResponseWriter, r *http.Request) {
|
func (tm *DAG) taskStatusHandler(w http.ResponseWriter, r *http.Request) {
|
||||||
taskID := r.URL.Query().Get("taskID")
|
taskID := r.URL.Query().Get("taskID")
|
||||||
if taskID == "" {
|
if taskID == "" {
|
||||||
http.Error(w, "taskID is missing", http.StatusBadRequest)
|
http.Error(w, `{"message": "taskID is missing"}`, http.StatusBadRequest)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
tm.mu.Lock()
|
manager, ok := tm.taskManager.Get(taskID)
|
||||||
manager, ok := tm.taskManager[taskID]
|
|
||||||
tm.mu.Unlock()
|
|
||||||
if !ok {
|
if !ok {
|
||||||
http.Error(w, "Invalid taskID", http.StatusNotFound)
|
http.Error(w, `{"message": "Invalid TaskID"}`, http.StatusNotFound)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
w.Header().Set("Content-Type", "application/json")
|
w.Header().Set("Content-Type", "application/json")
|
||||||
|
@@ -99,12 +99,14 @@
|
|||||||
fetch(`/task-result?taskID=${taskID}`)
|
fetch(`/task-result?taskID=${taskID}`)
|
||||||
.then(response => response.json())
|
.then(response => response.json())
|
||||||
.then(data => {
|
.then(data => {
|
||||||
const container = document.getElementById('result');
|
if(data?.message) {
|
||||||
let htmlContent = '';
|
document.getElementById('result').innerHTML = `
|
||||||
|
<p>Error loading task result. ${data.message}</p> <br> <a href="/form">Go back</a>`;
|
||||||
// Show final result in a table
|
} else {
|
||||||
htmlContent += `
|
const container = document.getElementById('result');
|
||||||
<h2>Final Task Result</h2>
|
let htmlContent = '';
|
||||||
|
htmlContent += `
|
||||||
|
<h2>Final Task Result <a href="/form">Go back</a></h2>
|
||||||
<table>
|
<table>
|
||||||
<tr>
|
<tr>
|
||||||
<th>Task ID</th>
|
<th>Task ID</th>
|
||||||
@@ -120,9 +122,7 @@
|
|||||||
</tr>
|
</tr>
|
||||||
</table>
|
</table>
|
||||||
`;
|
`;
|
||||||
|
htmlContent += `
|
||||||
// Show result per node
|
|
||||||
htmlContent += `
|
|
||||||
<div class="node-result">
|
<div class="node-result">
|
||||||
<h2>Result Per Node</h2>
|
<h2>Result Per Node</h2>
|
||||||
<table>
|
<table>
|
||||||
@@ -133,12 +133,10 @@
|
|||||||
<th>Node Result Data</th>
|
<th>Node Result Data</th>
|
||||||
</tr>
|
</tr>
|
||||||
`;
|
`;
|
||||||
|
for (const nodeID in data) {
|
||||||
// Loop through each node result and display in a table
|
if (nodeID !== "Result") {
|
||||||
for (const nodeID in data) {
|
const node = data[nodeID];
|
||||||
if (nodeID !== "Result") {
|
htmlContent += `
|
||||||
const node = data[nodeID];
|
|
||||||
htmlContent += `
|
|
||||||
<tr>
|
<tr>
|
||||||
<td>${node.NodeID}</td>
|
<td>${node.NodeID}</td>
|
||||||
<td class="${getStatusClass(node.Status)}">${node.Status}</td>
|
<td class="${getStatusClass(node.Status)}">${node.Status}</td>
|
||||||
@@ -146,13 +144,14 @@
|
|||||||
<td><pre>${JSON.stringify(node.Result.Data, null, 2)}</pre></td>
|
<td><pre>${JSON.stringify(node.Result.Data, null, 2)}</pre></td>
|
||||||
</tr>
|
</tr>
|
||||||
`;
|
`;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
htmlContent += '</table></div>';
|
||||||
|
container.innerHTML = htmlContent;
|
||||||
}
|
}
|
||||||
|
|
||||||
htmlContent += '</table></div>';
|
|
||||||
container.innerHTML = htmlContent;
|
|
||||||
})
|
})
|
||||||
.catch(error => {
|
.catch(error => {
|
||||||
|
console.log(error)
|
||||||
document.getElementById('result').innerHTML = '<p>Error loading task result.</p>';
|
document.getElementById('result').innerHTML = '<p>Error loading task result.</p>';
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
|
Reference in New Issue
Block a user