@@ -4,9 +4,9 @@ use libp2p::gossipsub::MessageAcceptance;
4
4
use ollama_workflows:: { Entry , Executor , ModelProvider , ProgramMemory , Workflow } ;
5
5
use serde:: Deserialize ;
6
6
7
- use crate :: node:: DriaComputeNode ;
8
- use crate :: utils:: payload:: { TaskRequestPayload , TaskResponsePayload } ;
7
+ use crate :: payloads:: { TaskErrorPayload , TaskRequestPayload , TaskResponsePayload } ;
9
8
use crate :: utils:: { get_current_time_nanos, DKNMessage } ;
9
+ use crate :: DriaComputeNode ;
10
10
11
11
use super :: ComputeHandler ;
12
12
@@ -32,6 +32,7 @@ impl ComputeHandler for WorkflowHandler {
32
32
message : DKNMessage ,
33
33
result_topic : & str ,
34
34
) -> Result < MessageAcceptance > {
35
+ let config = & node. config ;
35
36
let task = message. parse_payload :: < TaskRequestPayload < WorkflowPayload > > ( true ) ?;
36
37
37
38
// check if deadline is past or not
@@ -49,7 +50,7 @@ impl ComputeHandler for WorkflowHandler {
49
50
}
50
51
51
52
// check task inclusion via the bloom filter
52
- if !task. filter . contains ( & node . config . address ) ? {
53
+ if !task. filter . contains ( & config. address ) ? {
53
54
log:: info!(
54
55
"Task {} does not include this node within the filter." ,
55
56
task. task_id
@@ -59,23 +60,15 @@ impl ComputeHandler for WorkflowHandler {
59
60
return Ok ( MessageAcceptance :: Accept ) ;
60
61
}
61
62
62
- // obtain public key from the payload
63
- let task_public_key = hex:: decode ( & task. public_key ) ?;
64
-
65
63
// read model / provider from the task
66
- let ( model_provider, model) = node
67
- . config
64
+ let ( model_provider, model) = config
68
65
. model_config
69
66
. get_any_matching_model ( task. input . model ) ?;
70
67
log:: info!( "Using model {} for task {}" , model, task. task_id) ;
71
68
72
69
// prepare workflow executor
73
70
let executor = if model_provider == ModelProvider :: Ollama {
74
- Executor :: new_at (
75
- model,
76
- & node. config . ollama_config . host ,
77
- node. config . ollama_config . port ,
78
- )
71
+ Executor :: new_at ( model, & config. ollama_config . host , config. ollama_config . port )
79
72
} else {
80
73
Executor :: new ( model)
81
74
} ;
@@ -86,38 +79,52 @@ impl ComputeHandler for WorkflowHandler {
86
79
. map ( |prompt| Entry :: try_value_or_str ( & prompt) ) ;
87
80
88
81
// execute workflow with cancellation
89
- // TODO: is there a better way to handle this?
90
- let result: String ;
82
+ let exec_result: Result < String > ;
91
83
tokio:: select! {
92
84
_ = node. cancellation. cancelled( ) => {
93
85
log:: info!( "Received cancellation, quitting all tasks." ) ;
94
- return Ok ( MessageAcceptance :: Accept )
86
+ return Ok ( MessageAcceptance :: Accept ) ;
95
87
} ,
96
- exec_result = executor. execute( entry. as_ref( ) , task. input. workflow, & mut memory) => {
97
- match exec_result {
98
- Ok ( exec_result) => {
99
- result = exec_result;
100
- }
101
- Err ( e) => {
102
- return Err ( eyre!( "Workflow failed with error {}" , e) ) ;
103
- }
104
- }
88
+ exec_result_inner = executor. execute( entry. as_ref( ) , task. input. workflow, & mut memory) => {
89
+ exec_result = exec_result_inner. map_err( |e| eyre!( "{}" , e. to_string( ) ) ) ;
105
90
}
106
91
}
107
92
108
- // prepare signed and encrypted payload
109
- let payload = TaskResponsePayload :: new (
110
- result,
111
- & task. task_id ,
112
- & task_public_key,
113
- & node. config . secret_key ,
114
- ) ?;
115
- let payload_str = payload. to_string ( ) ?;
93
+ match exec_result {
94
+ Ok ( result) => {
95
+ // obtain public key from the payload
96
+ let task_public_key = hex:: decode ( & task. public_key ) ?;
97
+
98
+ // prepare signed and encrypted payload
99
+ let payload = TaskResponsePayload :: new (
100
+ result,
101
+ & task. task_id ,
102
+ & task_public_key,
103
+ & config. secret_key ,
104
+ ) ?;
105
+ let payload_str = serde_json:: to_string ( & payload) ?;
106
+
107
+ // publish the result
108
+ let message = DKNMessage :: new ( payload_str, result_topic) ;
109
+ node. publish ( message) ?;
110
+
111
+ // accept so that if there are others included in filter they can do the task
112
+ Ok ( MessageAcceptance :: Accept )
113
+ }
114
+ Err ( err) => {
115
+ log:: error!( "Task {} failed: {}" , task. task_id, err) ;
116
+
117
+ // prepare error payload
118
+ let error_payload = TaskErrorPayload :: new ( task. task_id , err. to_string ( ) ) ;
119
+ let error_payload_str = serde_json:: to_string ( & error_payload) ?;
116
120
117
- // publish the result
118
- let message = DKNMessage :: new ( payload_str , result_topic) ;
119
- node. publish ( message) ?;
121
+ // publish the error result for diagnostics
122
+ let message = DKNMessage :: new ( error_payload_str , result_topic) ;
123
+ node. publish ( message) ?;
120
124
121
- Ok ( MessageAcceptance :: Accept )
125
+ // ignore just in case, workflow may be bugged
126
+ Ok ( MessageAcceptance :: Ignore )
127
+ }
128
+ }
122
129
}
123
130
}
0 commit comments