@@ -20,10 +20,11 @@ use crate::lifecycle::DaemonRuntime;
2020/// Shared application state for all handlers.
2121pub type AppState = Arc < DaemonState > ;
2222
23- /// Combined daemon state: runtime + event bus.
23+ /// Combined daemon state: runtime + event bus + shared DB connection .
2424pub struct DaemonState {
2525 pub runtime : DaemonRuntime ,
2626 pub event_bus : flowctl_scheduler:: EventBus ,
27+ pub db : std:: sync:: Mutex < rusqlite:: Connection > ,
2728}
2829
2930/// GET /api/v1/health -- simple liveness check.
@@ -68,35 +69,11 @@ pub async fn status_handler(State(state): State<AppState>) -> impl IntoResponse
6869///
6970/// Returns a JSON array of epics. On database errors, returns 500.
7071pub async fn epics_handler ( State ( state) : State < AppState > ) -> impl IntoResponse {
71- let db_path = state
72- . runtime
73- . paths
74- . state_dir
75- . parent ( )
76- . map ( |flow_dir| flow_dir. join ( "flowctl.db" ) ) ;
77-
78- let Some ( db_path) = db_path else {
79- return (
80- StatusCode :: INTERNAL_SERVER_ERROR ,
81- Json ( serde_json:: json!( { "error" : "cannot resolve db path" } ) ) ,
82- ) ;
83- } ;
84-
85- match flowctl_db:: open ( & db_path) {
86- Ok ( conn) => {
87- let repo = flowctl_db:: EpicRepo :: new ( & conn) ;
88- match repo. list ( None ) {
89- Ok ( epics) => ( StatusCode :: OK , Json ( serde_json:: to_value ( & epics) . unwrap ( ) ) ) ,
90- Err ( e) => (
91- StatusCode :: INTERNAL_SERVER_ERROR ,
92- Json ( serde_json:: json!( { "error" : e. to_string( ) } ) ) ,
93- ) ,
94- }
95- }
96- Err ( e) => (
97- StatusCode :: INTERNAL_SERVER_ERROR ,
98- Json ( serde_json:: json!( { "error" : format!( "db open failed: {e}" ) } ) ) ,
99- ) ,
72+ let conn = state. db . lock ( ) . unwrap ( ) ;
73+ let repo = flowctl_db:: EpicRepo :: new ( & conn) ;
74+ match repo. list ( None ) {
75+ Ok ( epics) => ( StatusCode :: OK , Json ( serde_json:: to_value ( & epics) . unwrap ( ) ) ) ,
76+ Err ( e) => db_error ( & e. to_string ( ) ) ,
10077 }
10178}
10279
@@ -105,40 +82,16 @@ pub async fn tasks_handler(
10582 State ( state) : State < AppState > ,
10683 axum:: extract:: Query ( params) : axum:: extract:: Query < TasksQuery > ,
10784) -> impl IntoResponse {
108- let db_path = state
109- . runtime
110- . paths
111- . state_dir
112- . parent ( )
113- . map ( |flow_dir| flow_dir. join ( "flowctl.db" ) ) ;
114-
115- let Some ( db_path) = db_path else {
116- return (
117- StatusCode :: INTERNAL_SERVER_ERROR ,
118- Json ( serde_json:: json!( { "error" : "cannot resolve db path" } ) ) ,
119- ) ;
85+ let conn = state. db . lock ( ) . unwrap ( ) ;
86+ let repo = flowctl_db:: TaskRepo :: new ( & conn) ;
87+ let result = if let Some ( ref epic_id) = params. epic_id {
88+ repo. list_by_epic ( epic_id)
89+ } else {
90+ repo. list_all ( None , None )
12091 } ;
121-
122- match flowctl_db:: open ( & db_path) {
123- Ok ( conn) => {
124- let repo = flowctl_db:: TaskRepo :: new ( & conn) ;
125- let result = if let Some ( ref epic_id) = params. epic_id {
126- repo. list_by_epic ( epic_id)
127- } else {
128- repo. list_all ( None , None )
129- } ;
130- match result {
131- Ok ( tasks) => ( StatusCode :: OK , Json ( serde_json:: to_value ( & tasks) . unwrap ( ) ) ) ,
132- Err ( e) => (
133- StatusCode :: INTERNAL_SERVER_ERROR ,
134- Json ( serde_json:: json!( { "error" : e. to_string( ) } ) ) ,
135- ) ,
136- }
137- }
138- Err ( e) => (
139- StatusCode :: INTERNAL_SERVER_ERROR ,
140- Json ( serde_json:: json!( { "error" : format!( "db open failed: {e}" ) } ) ) ,
141- ) ,
92+ match result {
93+ Ok ( tasks) => ( StatusCode :: OK , Json ( serde_json:: to_value ( & tasks) . unwrap ( ) ) ) ,
94+ Err ( e) => db_error ( & e. to_string ( ) ) ,
14295 }
14396}
14497
@@ -155,10 +108,7 @@ pub async fn create_task_handler(
155108 State ( state) : State < AppState > ,
156109 Json ( body) : Json < CreateTaskRequest > ,
157110) -> impl IntoResponse {
158- let conn = match open_db ( & state) {
159- Ok ( c) => c,
160- Err ( resp) => return resp,
161- } ;
111+ let conn = state. db . lock ( ) . unwrap ( ) ;
162112 let task = flowctl_core:: types:: Task {
163113 schema_version : 1 ,
164114 id : body. id . clone ( ) ,
@@ -188,10 +138,7 @@ pub async fn start_task_handler(
188138 State ( state) : State < AppState > ,
189139 Json ( body) : Json < TaskIdRequest > ,
190140) -> impl IntoResponse {
191- let conn = match open_db ( & state) {
192- Ok ( c) => c,
193- Err ( resp) => return resp,
194- } ;
141+ let conn = state. db . lock ( ) . unwrap ( ) ;
195142 let repo = flowctl_db:: TaskRepo :: new ( & conn) ;
196143 match repo. update_status ( & body. task_id , flowctl_core:: state_machine:: Status :: InProgress ) {
197144 Ok ( ( ) ) => ( StatusCode :: OK , Json ( serde_json:: json!( { "success" : true , "id" : body. task_id} ) ) ) ,
@@ -204,10 +151,7 @@ pub async fn done_task_handler(
204151 State ( state) : State < AppState > ,
205152 Json ( body) : Json < TaskIdRequest > ,
206153) -> impl IntoResponse {
207- let conn = match open_db ( & state) {
208- Ok ( c) => c,
209- Err ( resp) => return resp,
210- } ;
154+ let conn = state. db . lock ( ) . unwrap ( ) ;
211155 let repo = flowctl_db:: TaskRepo :: new ( & conn) ;
212156 match repo. update_status ( & body. task_id , flowctl_core:: state_machine:: Status :: Done ) {
213157 Ok ( ( ) ) => ( StatusCode :: OK , Json ( serde_json:: json!( { "success" : true , "id" : body. task_id} ) ) ) ,
@@ -229,16 +173,9 @@ pub struct TaskIdRequest {
229173 pub task_id : String ,
230174}
231175
232- /// Helper: open a DB connection from daemon state.
233- fn open_db ( state : & DaemonState ) -> Result < rusqlite:: Connection , ( StatusCode , Json < serde_json:: Value > ) > {
234- let db_path = state. runtime . paths . state_dir . parent ( )
235- . map ( |flow_dir| flow_dir. join ( "flowctl.db" ) ) ;
236- let Some ( db_path) = db_path else {
237- return Err ( ( StatusCode :: INTERNAL_SERVER_ERROR , Json ( serde_json:: json!( { "error" : "cannot resolve db path" } ) ) ) ) ;
238- } ;
239- flowctl_db:: open ( & db_path) . map_err ( |e| {
240- ( StatusCode :: INTERNAL_SERVER_ERROR , Json ( serde_json:: json!( { "error" : format!( "db open failed: {e}" ) } ) ) )
241- } )
176+ /// Helper: acquire DB lock from shared state.
177+ fn db_error ( msg : & str ) -> ( StatusCode , Json < serde_json:: Value > ) {
178+ ( StatusCode :: INTERNAL_SERVER_ERROR , Json ( serde_json:: json!( { "error" : msg} ) ) )
242179}
243180
244181/// GET /api/v1/events -- WebSocket upgrade for live event streaming.
0 commit comments