11import uuid
22from dataclasses import asdict
3+ from datetime import datetime
34from typing import Dict , List
45
6+ from fastapi import BackgroundTasks
7+
8+ from studio .app .common .core .experiment .experiment_reader import ExptConfigReader
9+ from studio .app .common .core .experiment .experiment_record_services import (
10+ ExperimentRecordService ,
11+ )
512from studio .app .common .core .experiment .experiment_writer import ExptConfigWriter
613from studio .app .common .core .rules .runner import Runner
714from studio .app .common .core .snakemake .smk import FlowConfig , Rule , SmkParam
1219from studio .app .common .core .snakemake .snakemake_reader import SmkParamReader
1320from studio .app .common .core .snakemake .snakemake_rule import SmkRule
1421from studio .app .common .core .snakemake .snakemake_writer import SmkConfigWriter
15- from studio .app .common .core .workflow .workflow import NodeType , NodeTypeUtil , RunItem
22+ from studio .app .common .core .workflow .workflow import (
23+ NodeType ,
24+ NodeTypeUtil ,
25+ OutputPath ,
26+ OutputType ,
27+ RunItem ,
28+ WorkflowRunStatus ,
29+ )
1630from studio .app .common .core .workflow .workflow_params import get_typecheck_params
1731from studio .app .common .core .workflow .workflow_writer import WorkflowConfigWriter
32+ from studio .app .const import DATE_FORMAT
1833
1934
2035class WorkflowRunner :
@@ -47,7 +62,7 @@ def create_workflow_unique_id() -> str:
4762 new_unique_id = str (uuid .uuid4 ())[:8 ]
4863 return new_unique_id
4964
50- def run_workflow (self , background_tasks ):
65+ def run_workflow (self , background_tasks : BackgroundTasks ):
5166 self .set_smk_config ()
5267
5368 snakemake_params : SmkParam = get_typecheck_params (
@@ -68,6 +83,54 @@ def run_workflow(self, background_tasks):
6883 snakemake_execute , self .workspace_id , self .unique_id , snakemake_params
6984 )
7085
86+ def finish_workflow_without_run (
87+ self , status : WorkflowRunStatus = WorkflowRunStatus .SUCCESS
88+ ):
89+ """
90+ Saves the settings and finishes the workflow without actually running it.
91+ - Function solely for creating experiment record.
92+ """
93+
94+ # Load current configs
95+ expt_config = ExptConfigReader .read (self .workspace_id , self .unique_id )
96+
97+ # Construct update data (ExptConfig.*)
98+ update_expt_config = ExptConfigReader .create_empty_experiment_config ()
99+ now = datetime .now ().strftime (DATE_FORMAT )
100+ update_expt_config .success = status .value
101+ update_expt_config .finished_at = now
102+ update_expt_config .data_usage = 0
103+
104+ # Construct update data (ExptConfig.function)
105+ update_expt_config .function = {}
106+ for node_id , function in expt_config .function .items ():
107+ function .success = WorkflowRunStatus .SUCCESS .value
108+ function .outputPaths = {
109+ "empty" : OutputPath (
110+ path = "empty" ,
111+ type = OutputType .EMPTY ,
112+ max_index = 1 ,
113+ )
114+ }
115+
116+ update_expt_config .function [node_id ] = function
117+
118+ # Prepare data (dict variable) for overwriting the config file
119+ update_expt_config_dict = {
120+ k : v for k , v in asdict (update_expt_config ).items () if v is not None
121+ }
122+
123+ # Overwrite config file
124+ ExptConfigWriter (self .workspace_id , self .unique_id ).overwrite (
125+ update_expt_config_dict
126+ )
127+
128+ # Update experiment database record
129+ if ExperimentRecordService .is_available ():
130+ ExperimentRecordService .regist_record_on_workflow_completed (
131+ self .workspace_id , self .unique_id
132+ )
133+
71134 def set_smk_config (self ):
72135 rules , last_output = self .rulefile ()
73136
0 commit comments