panda-server-source 0.8.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (375) hide show
  1. panda_server_source-0.8.0.dist-info/METADATA +55 -0
  2. panda_server_source-0.8.0.dist-info/RECORD +375 -0
  3. panda_server_source-0.8.0.dist-info/WHEEL +4 -0
  4. panda_server_source-0.8.0.dist-info/licenses/LICENSE.txt +202 -0
  5. pandajedi/__init__.py +0 -0
  6. pandajedi/jedibrokerage/AtlasAnalJobBroker.py +2343 -0
  7. pandajedi/jedibrokerage/AtlasBrokerUtils.py +1292 -0
  8. pandajedi/jedibrokerage/AtlasProdJobBroker.py +2064 -0
  9. pandajedi/jedibrokerage/AtlasProdTaskBroker.py +629 -0
  10. pandajedi/jedibrokerage/GenJobBroker.py +381 -0
  11. pandajedi/jedibrokerage/JobBrokerBase.py +133 -0
  12. pandajedi/jedibrokerage/TaskBrokerBase.py +15 -0
  13. pandajedi/jedibrokerage/__init__.py +0 -0
  14. pandajedi/jediconfig/__init__.py +0 -0
  15. pandajedi/jediconfig/jedi_config.py +40 -0
  16. pandajedi/jedicore/FactoryBase.py +182 -0
  17. pandajedi/jedicore/Interaction.py +433 -0
  18. pandajedi/jedicore/JediDBProxy.py +56 -0
  19. pandajedi/jedicore/JediDBProxyPool.py +37 -0
  20. pandajedi/jedicore/JediDBSchemaInfo.py +17 -0
  21. pandajedi/jedicore/JediException.py +13 -0
  22. pandajedi/jedicore/JediTaskBuffer.py +984 -0
  23. pandajedi/jedicore/JediTaskBufferInterface.py +50 -0
  24. pandajedi/jedicore/MsgWrapper.py +124 -0
  25. pandajedi/jedicore/ProcessUtils.py +34 -0
  26. pandajedi/jedicore/SiteCandidate.py +90 -0
  27. pandajedi/jedicore/ThreadUtils.py +205 -0
  28. pandajedi/jedicore/__init__.py +0 -0
  29. pandajedi/jediddm/AtlasDDMClient.py +1708 -0
  30. pandajedi/jediddm/DDMClientBase.py +16 -0
  31. pandajedi/jediddm/DDMInterface.py +83 -0
  32. pandajedi/jediddm/GenDDMClient.py +17 -0
  33. pandajedi/jediddm/__init__.py +0 -0
  34. pandajedi/jedidog/AtlasAnalWatchDog.py +648 -0
  35. pandajedi/jedidog/AtlasDataCarouselWatchDog.py +189 -0
  36. pandajedi/jedidog/AtlasDataLocalityUpdaterWatchDog.py +215 -0
  37. pandajedi/jedidog/AtlasProdWatchDog.py +443 -0
  38. pandajedi/jedidog/AtlasQueueFillerWatchDog.py +800 -0
  39. pandajedi/jedidog/AtlasTaskWithholderWatchDog.py +245 -0
  40. pandajedi/jedidog/AtlasWorkflowManagerWatchDog.py +63 -0
  41. pandajedi/jedidog/GenWatchDog.py +21 -0
  42. pandajedi/jedidog/JumboWatchDog.py +147 -0
  43. pandajedi/jedidog/TypicalWatchDogBase.py +122 -0
  44. pandajedi/jedidog/WatchDogBase.py +53 -0
  45. pandajedi/jedidog/__init__.py +0 -0
  46. pandajedi/jediexec/reniceJEDI.py +25 -0
  47. pandajedi/jedigen/AtlasTaskGenerator.py +110 -0
  48. pandajedi/jedigen/TaskGeneratorBase.py +15 -0
  49. pandajedi/jedigen/__init__.py +0 -0
  50. pandajedi/jedimsgprocessor/__init__.py +0 -0
  51. pandajedi/jedimsgprocessor/ai_parameter_adjuster_msg_processor +71 -0
  52. pandajedi/jedimsgprocessor/atlas_idds_msg_processor.py +66 -0
  53. pandajedi/jedimsgprocessor/base_msg_processor.py +33 -0
  54. pandajedi/jedimsgprocessor/forwarding_msg_processor.py +29 -0
  55. pandajedi/jedimsgprocessor/hpo_msg_processor.py +93 -0
  56. pandajedi/jedimsgprocessor/jedi_contents_feeder_msg_processor.py +63 -0
  57. pandajedi/jedimsgprocessor/jedi_job_generator_msg_processor.py +185 -0
  58. pandajedi/jedimsgprocessor/jedi_post_processor_msg_processor.py +82 -0
  59. pandajedi/jedimsgprocessor/kafka_msg_processor.py +44 -0
  60. pandajedi/jedimsgprocessor/panda_callback_msg_processor.py +182 -0
  61. pandajedi/jedimsgprocessor/panda_to_jedi_msg_processor.py +74 -0
  62. pandajedi/jedimsgprocessor/processing_msg_processor.py +134 -0
  63. pandajedi/jedimsgprocessor/status_report_msg_processor.py +129 -0
  64. pandajedi/jedimsgprocessor/tape_carousel_msg_processor.py +118 -0
  65. pandajedi/jedimsgprocessor/workflow_manager_msg_processor.py +89 -0
  66. pandajedi/jediorder/ContentsFeeder.py +785 -0
  67. pandajedi/jediorder/JediDaemon.py +27 -0
  68. pandajedi/jediorder/JediKnight.py +55 -0
  69. pandajedi/jediorder/JediMaster.py +238 -0
  70. pandajedi/jediorder/JediMsgProcessor.py +32 -0
  71. pandajedi/jediorder/JobBroker.py +33 -0
  72. pandajedi/jediorder/JobGenerator.py +2763 -0
  73. pandajedi/jediorder/JobSplitter.py +308 -0
  74. pandajedi/jediorder/JobThrottler.py +28 -0
  75. pandajedi/jediorder/PostProcessor.py +166 -0
  76. pandajedi/jediorder/TaskBroker.py +268 -0
  77. pandajedi/jediorder/TaskCommando.py +334 -0
  78. pandajedi/jediorder/TaskGenerator.py +17 -0
  79. pandajedi/jediorder/TaskRefiner.py +611 -0
  80. pandajedi/jediorder/TaskSetupper.py +17 -0
  81. pandajedi/jediorder/WatchDog.py +79 -0
  82. pandajedi/jediorder/__init__.py +0 -0
  83. pandajedi/jedipprocess/AtlasAnalPostProcessor.py +404 -0
  84. pandajedi/jedipprocess/AtlasPostProcessorUtils.py +50 -0
  85. pandajedi/jedipprocess/AtlasProdPostProcessor.py +178 -0
  86. pandajedi/jedipprocess/GenPostProcessor.py +35 -0
  87. pandajedi/jedipprocess/MailTemplates.py +185 -0
  88. pandajedi/jedipprocess/PostProcessorBase.py +269 -0
  89. pandajedi/jedipprocess/__init__.py +0 -0
  90. pandajedi/jedirefine/AtlasAnalTaskRefiner.py +259 -0
  91. pandajedi/jedirefine/AtlasProdTaskRefiner.py +162 -0
  92. pandajedi/jedirefine/GenTaskRefiner.py +61 -0
  93. pandajedi/jedirefine/RefinerUtils.py +154 -0
  94. pandajedi/jedirefine/TaskRefinerBase.py +996 -0
  95. pandajedi/jedirefine/__init__.py +0 -0
  96. pandajedi/jedisetup/AtlasTaskSetupper.py +309 -0
  97. pandajedi/jedisetup/GenTaskSetupper.py +16 -0
  98. pandajedi/jedisetup/SimpleTaskSetupper.py +152 -0
  99. pandajedi/jedisetup/TaskSetupperBase.py +15 -0
  100. pandajedi/jedisetup/__init__.py +0 -0
  101. pandajedi/jeditest/SchemaChecker.py +41 -0
  102. pandajedi/jeditest/addContWoSoTask.py +54 -0
  103. pandajedi/jeditest/addDataCarouselRequest.py +47 -0
  104. pandajedi/jeditest/addEventServiceTask.py +101 -0
  105. pandajedi/jeditest/addHpoTask.py +81 -0
  106. pandajedi/jeditest/addIDDSStageInRequest.py +56 -0
  107. pandajedi/jeditest/addNonAtlasTask.py +71 -0
  108. pandajedi/jeditest/addNonAtlasTaskEnc.py +64 -0
  109. pandajedi/jeditest/addTestTask.py +124 -0
  110. pandajedi/jeditest/addTestTaskParamToDEFT.py +70 -0
  111. pandajedi/jeditest/addTestTaskWithMerger.py +97 -0
  112. pandajedi/jeditest/brokerTest.py +78 -0
  113. pandajedi/jeditest/cancelDataCarouselRequest.py +35 -0
  114. pandajedi/jeditest/contentsFeederTest.py +28 -0
  115. pandajedi/jeditest/contentsFeederTestWithTask.py +18 -0
  116. pandajedi/jeditest/ddmTest.py +4 -0
  117. pandajedi/jeditest/jobGenForOneTask.py +38 -0
  118. pandajedi/jeditest/jobGeneratorTest.py +43 -0
  119. pandajedi/jeditest/jobSplitterTest.py +104 -0
  120. pandajedi/jeditest/jobThrottlerTest.py +22 -0
  121. pandajedi/jeditest/msgProcessorTest.py +9 -0
  122. pandajedi/jeditest/postProcessorTest.py +18 -0
  123. pandajedi/jeditest/resubmitDataCarouselRequest.py +35 -0
  124. pandajedi/jeditest/resubmitTaskParam.py +20 -0
  125. pandajedi/jeditest/taskBrokerTest.py +22 -0
  126. pandajedi/jeditest/taskBrokerTestWithTask.py +38 -0
  127. pandajedi/jeditest/taskBufferTest.py +5 -0
  128. pandajedi/jeditest/taskCommandoTest.py +28 -0
  129. pandajedi/jeditest/taskRefinerTest.py +30 -0
  130. pandajedi/jeditest/testOneTaskToRefine.py +49 -0
  131. pandajedi/jeditest/testOneTaskToTaskBroker.py +42 -0
  132. pandajedi/jeditest/testPandaDDMMap.py +62 -0
  133. pandajedi/jeditest/updateDataCarouselRequestParams.py +50 -0
  134. pandajedi/jeditest/watchDogTest.py +25 -0
  135. pandajedi/jeditest/workQueueTest.py +22 -0
  136. pandajedi/jedithrottle/AtlasAnalJobThrottler.py +19 -0
  137. pandajedi/jedithrottle/AtlasProdJobThrottler.py +18 -0
  138. pandajedi/jedithrottle/GenJobThrottler.py +26 -0
  139. pandajedi/jedithrottle/JobThrottlerBase.py +496 -0
  140. pandajedi/jedithrottle/__init__.py +0 -0
  141. pandaserver/__init__.py +0 -0
  142. pandaserver/api/__init__.py +0 -0
  143. pandaserver/api/v1/__init__.py +0 -0
  144. pandaserver/api/v1/common.py +339 -0
  145. pandaserver/api/v1/credential_management_api.py +372 -0
  146. pandaserver/api/v1/data_carousel_api.py +264 -0
  147. pandaserver/api/v1/event_api.py +269 -0
  148. pandaserver/api/v1/file_server_api.py +942 -0
  149. pandaserver/api/v1/harvester_api.py +445 -0
  150. pandaserver/api/v1/http_client.py +166 -0
  151. pandaserver/api/v1/idds_api.py +180 -0
  152. pandaserver/api/v1/job_api.py +463 -0
  153. pandaserver/api/v1/metaconfig_api.py +122 -0
  154. pandaserver/api/v1/pilot_api.py +895 -0
  155. pandaserver/api/v1/statistics_api.py +207 -0
  156. pandaserver/api/v1/system_api.py +186 -0
  157. pandaserver/api/v1/task_api.py +1520 -0
  158. pandaserver/api/v1/tests/__init__.py +0 -0
  159. pandaserver/api/v1/tests/credential_management_api_tests.py +116 -0
  160. pandaserver/api/v1/tests/data_carousel_api_tests.py +82 -0
  161. pandaserver/api/v1/tests/harvester_api_tests.py +188 -0
  162. pandaserver/api/v1/tests/idds_api_tests.py +45 -0
  163. pandaserver/api/v1/tests/job_api_tests.py +112 -0
  164. pandaserver/api/v1/tests/pilot_api_tests.py +154 -0
  165. pandaserver/api/v1/tests/statistics_api_tests.py +104 -0
  166. pandaserver/api/v1/tests/system_api_tests.py +58 -0
  167. pandaserver/api/v1/tests/task_api_tests.py +590 -0
  168. pandaserver/api/v1/version.py +2 -0
  169. pandaserver/api/v1/workflow_api.py +136 -0
  170. pandaserver/brokerage/SiteMapper.py +406 -0
  171. pandaserver/brokerage/__init__.py +0 -0
  172. pandaserver/brokerage/broker.py +272 -0
  173. pandaserver/config/__init__.py +0 -0
  174. pandaserver/config/config_utils.py +15 -0
  175. pandaserver/config/daemon_config.py +29 -0
  176. pandaserver/config/mcp_config.py +38 -0
  177. pandaserver/config/panda_config.py +233 -0
  178. pandaserver/configurator/Carbon.py +65 -0
  179. pandaserver/configurator/Configurator.py +908 -0
  180. pandaserver/configurator/__init__.py +0 -0
  181. pandaserver/configurator/aux.py +73 -0
  182. pandaserver/daemons/__init__.py +0 -0
  183. pandaserver/daemons/master.py +110 -0
  184. pandaserver/daemons/master_systemd.py +79 -0
  185. pandaserver/daemons/scripts/__init__.py +0 -0
  186. pandaserver/daemons/scripts/add_main.py +264 -0
  187. pandaserver/daemons/scripts/add_sub.py +221 -0
  188. pandaserver/daemons/scripts/cache_pilots.py +47 -0
  189. pandaserver/daemons/scripts/cache_schedconfig.py +286 -0
  190. pandaserver/daemons/scripts/carbon.py +50 -0
  191. pandaserver/daemons/scripts/configurator.py +94 -0
  192. pandaserver/daemons/scripts/copyArchive.py +1387 -0
  193. pandaserver/daemons/scripts/datasetManager.py +1154 -0
  194. pandaserver/daemons/scripts/dummy_test.py +25 -0
  195. pandaserver/daemons/scripts/evpPD2P.py +144 -0
  196. pandaserver/daemons/scripts/hs_scrapers.py +264 -0
  197. pandaserver/daemons/scripts/metric_collector.py +927 -0
  198. pandaserver/daemons/scripts/panda_activeusers_query.py +80 -0
  199. pandaserver/daemons/scripts/pilotStreaming.py +109 -0
  200. pandaserver/daemons/scripts/process_workflow_files_daemon.py +166 -0
  201. pandaserver/daemons/scripts/recover_lost_files_daemon.py +177 -0
  202. pandaserver/daemons/scripts/task_evaluator.py +405 -0
  203. pandaserver/daemons/scripts/tmpwatch.py +70 -0
  204. pandaserver/daemons/scripts/worker_synchronization.py +97 -0
  205. pandaserver/daemons/utils.py +753 -0
  206. pandaserver/dataservice/DataServiceUtils.py +323 -0
  207. pandaserver/dataservice/ErrorCode.py +25 -0
  208. pandaserver/dataservice/RecoverLostFilesCore.py +322 -0
  209. pandaserver/dataservice/__init__.py +0 -0
  210. pandaserver/dataservice/activator.py +79 -0
  211. pandaserver/dataservice/adder_atlas_plugin.py +1106 -0
  212. pandaserver/dataservice/adder_dummy_plugin.py +31 -0
  213. pandaserver/dataservice/adder_gen.py +954 -0
  214. pandaserver/dataservice/adder_plugin_base.py +27 -0
  215. pandaserver/dataservice/adder_result.py +75 -0
  216. pandaserver/dataservice/adder_simple_plugin.py +160 -0
  217. pandaserver/dataservice/closer.py +247 -0
  218. pandaserver/dataservice/closer_atlas_plugin.py +90 -0
  219. pandaserver/dataservice/ddm.py +1381 -0
  220. pandaserver/dataservice/ddm_handler.py +95 -0
  221. pandaserver/dataservice/dyn_data_distributer.py +824 -0
  222. pandaserver/dataservice/event_lookup_client_ei.py +77 -0
  223. pandaserver/dataservice/event_picker.py +268 -0
  224. pandaserver/dataservice/finisher.py +194 -0
  225. pandaserver/dataservice/setupper.py +225 -0
  226. pandaserver/dataservice/setupper_atlas_plugin.py +1851 -0
  227. pandaserver/dataservice/setupper_dummy_plugin.py +47 -0
  228. pandaserver/dataservice/setupper_plugin_base.py +67 -0
  229. pandaserver/jobdispatcher/DispatcherUtils.py +35 -0
  230. pandaserver/jobdispatcher/ErrorCode.py +19 -0
  231. pandaserver/jobdispatcher/JobDispatcher.py +1625 -0
  232. pandaserver/jobdispatcher/Protocol.py +443 -0
  233. pandaserver/jobdispatcher/Watcher.py +186 -0
  234. pandaserver/jobdispatcher/__init__.py +0 -0
  235. pandaserver/pandamcp/__init__.py +0 -0
  236. pandaserver/pandamcp/mcp_main.py +56 -0
  237. pandaserver/pandamcp/mcp_test_client.py +95 -0
  238. pandaserver/pandamcp/mcp_utils.py +74 -0
  239. pandaserver/proxycache/__init__.py +0 -0
  240. pandaserver/proxycache/panda_proxy_cache.py +240 -0
  241. pandaserver/proxycache/token_cache.py +141 -0
  242. pandaserver/server/.gacl +6 -0
  243. pandaserver/server/panda.py +539 -0
  244. pandaserver/srvcore/CoreUtils.py +572 -0
  245. pandaserver/srvcore/MailUtils.py +106 -0
  246. pandaserver/srvcore/__init__.py +0 -0
  247. pandaserver/srvcore/allowed_methods.py +100 -0
  248. pandaserver/srvcore/oidc_utils.py +152 -0
  249. pandaserver/srvcore/panda_request.py +196 -0
  250. pandaserver/srvcore/srv_msg_utils.py +42 -0
  251. pandaserver/taskbuffer/ConBridge.py +513 -0
  252. pandaserver/taskbuffer/DBProxyPool.py +95 -0
  253. pandaserver/taskbuffer/DataCarousel.py +3053 -0
  254. pandaserver/taskbuffer/DatasetSpec.py +137 -0
  255. pandaserver/taskbuffer/DdmSpec.py +201 -0
  256. pandaserver/taskbuffer/ErrorCode.py +87 -0
  257. pandaserver/taskbuffer/EventServiceUtils.py +396 -0
  258. pandaserver/taskbuffer/FileSpec.py +290 -0
  259. pandaserver/taskbuffer/GlobalShares.py +244 -0
  260. pandaserver/taskbuffer/HarvesterMetricsSpec.py +92 -0
  261. pandaserver/taskbuffer/Initializer.py +82 -0
  262. pandaserver/taskbuffer/InputChunk.py +1080 -0
  263. pandaserver/taskbuffer/JediCacheSpec.py +57 -0
  264. pandaserver/taskbuffer/JediDatasetSpec.py +588 -0
  265. pandaserver/taskbuffer/JediFileSpec.py +242 -0
  266. pandaserver/taskbuffer/JediTaskSpec.py +1687 -0
  267. pandaserver/taskbuffer/JobSpec.py +1006 -0
  268. pandaserver/taskbuffer/JobUtils.py +232 -0
  269. pandaserver/taskbuffer/NucleusSpec.py +116 -0
  270. pandaserver/taskbuffer/OraDBProxy.py +174 -0
  271. pandaserver/taskbuffer/PanDAMsgProcessor.py +8 -0
  272. pandaserver/taskbuffer/PandaDBSchemaInfo.py +18 -0
  273. pandaserver/taskbuffer/ParseJobXML.py +350 -0
  274. pandaserver/taskbuffer/PickleFileSpec.py +18 -0
  275. pandaserver/taskbuffer/PickleJobSpec.py +25 -0
  276. pandaserver/taskbuffer/PrioUtil.py +40 -0
  277. pandaserver/taskbuffer/ProcessGroups.py +111 -0
  278. pandaserver/taskbuffer/ResourceSpec.py +175 -0
  279. pandaserver/taskbuffer/SQLDumper.py +37 -0
  280. pandaserver/taskbuffer/SQLManager.py +60 -0
  281. pandaserver/taskbuffer/SiteSpec.py +304 -0
  282. pandaserver/taskbuffer/SupErrors.py +10 -0
  283. pandaserver/taskbuffer/TaskBuffer.py +2882 -0
  284. pandaserver/taskbuffer/TaskBufferInterface.py +163 -0
  285. pandaserver/taskbuffer/Utils.py +848 -0
  286. pandaserver/taskbuffer/WorkQueue.py +227 -0
  287. pandaserver/taskbuffer/WorkQueueMapper.py +203 -0
  288. pandaserver/taskbuffer/WorkerSpec.py +143 -0
  289. pandaserver/taskbuffer/WrappedCursor.py +487 -0
  290. pandaserver/taskbuffer/WrappedPickle.py +88 -0
  291. pandaserver/taskbuffer/WrappedPostgresConn.py +24 -0
  292. pandaserver/taskbuffer/__init__.py +0 -0
  293. pandaserver/taskbuffer/db_proxy_mods/OraDBProxy_structure.png +0 -0
  294. pandaserver/taskbuffer/db_proxy_mods/__init__.py +7 -0
  295. pandaserver/taskbuffer/db_proxy_mods/base_module.py +841 -0
  296. pandaserver/taskbuffer/db_proxy_mods/data_carousel_module.py +772 -0
  297. pandaserver/taskbuffer/db_proxy_mods/entity_module.py +3804 -0
  298. pandaserver/taskbuffer/db_proxy_mods/job_complex_module.py +5661 -0
  299. pandaserver/taskbuffer/db_proxy_mods/job_standalone_module.py +2640 -0
  300. pandaserver/taskbuffer/db_proxy_mods/metrics_module.py +874 -0
  301. pandaserver/taskbuffer/db_proxy_mods/misc_standalone_module.py +4272 -0
  302. pandaserver/taskbuffer/db_proxy_mods/task_complex_module.py +6172 -0
  303. pandaserver/taskbuffer/db_proxy_mods/task_event_module.py +4953 -0
  304. pandaserver/taskbuffer/db_proxy_mods/task_standalone_module.py +4999 -0
  305. pandaserver/taskbuffer/db_proxy_mods/task_utils_module.py +2063 -0
  306. pandaserver/taskbuffer/db_proxy_mods/worker_module.py +1944 -0
  307. pandaserver/taskbuffer/db_proxy_mods/workflow_module.py +832 -0
  308. pandaserver/taskbuffer/retryModule.py +552 -0
  309. pandaserver/taskbuffer/task_split_rules.py +308 -0
  310. pandaserver/taskbuffer/workflow_processor.py +249 -0
  311. pandaserver/taskbuffer/wrapped_oracle_conn.py +18 -0
  312. pandaserver/test/SchemaChecker.py +40 -0
  313. pandaserver/test/__init__.py +0 -0
  314. pandaserver/test/banUser.py +43 -0
  315. pandaserver/test/boostPrio.py +19 -0
  316. pandaserver/test/boostUser.py +35 -0
  317. pandaserver/test/callbackDDM.py +11 -0
  318. pandaserver/test/daod_on_demand.py +95 -0
  319. pandaserver/test/finishJob.py +184 -0
  320. pandaserver/test/finishTaskJEDI.py +11 -0
  321. pandaserver/test/getJobs.py +53 -0
  322. pandaserver/test/killJob.py +79 -0
  323. pandaserver/test/killJobLowPrio.py +99 -0
  324. pandaserver/test/killJobsInTask.py +56 -0
  325. pandaserver/test/killTask.py +80 -0
  326. pandaserver/test/killTaskJEDI.py +11 -0
  327. pandaserver/test/killUser.py +83 -0
  328. pandaserver/test/lsst/README.txt +7 -0
  329. pandaserver/test/lsst/lsstSubmit.py +139 -0
  330. pandaserver/test/lsst/lsstSubmitMERGEtest.py +141 -0
  331. pandaserver/test/lsst/lsstSubmitPhosim332.py +53 -0
  332. pandaserver/test/lsst/prepare-client-tarball-from-bigpanda-server.sh +41 -0
  333. pandaserver/test/reassignJobs.py +17 -0
  334. pandaserver/test/reassignSite.py +82 -0
  335. pandaserver/test/reassignTask.py +117 -0
  336. pandaserver/test/reassignWaiting.py +39 -0
  337. pandaserver/test/recoverLostFiles.py +7 -0
  338. pandaserver/test/reloadInputDS.py +51 -0
  339. pandaserver/test/sendCommandToJob.py +26 -0
  340. pandaserver/test/setDebugMode.py +38 -0
  341. pandaserver/test/setPriority.py +28 -0
  342. pandaserver/test/testEvgen.py +60 -0
  343. pandaserver/test/testEvgen17.py +58 -0
  344. pandaserver/test/testG4sim.py +81 -0
  345. pandaserver/test/testG4sim17.py +90 -0
  346. pandaserver/test/testGlobalShares.py +131 -0
  347. pandaserver/test/testReco.py +103 -0
  348. pandaserver/test/testSimulReco14.py +98 -0
  349. pandaserver/test/testSiteMap.py +26 -0
  350. pandaserver/test/testUpdateWorkerPilotStatus.py +9 -0
  351. pandaserver/userinterface/Client.py +1686 -0
  352. pandaserver/userinterface/UserIF.py +1799 -0
  353. pandaserver/userinterface/__init__.py +0 -0
  354. pandaserver/workflow/__init__.py +0 -0
  355. pandaserver/workflow/data_handler_plugins/base_data_handler.py +48 -0
  356. pandaserver/workflow/data_handler_plugins/ddm_collection_data_handler.py +100 -0
  357. pandaserver/workflow/data_handler_plugins/panda_task_data_handler.py +140 -0
  358. pandaserver/workflow/pcwl_test.py +122 -0
  359. pandaserver/workflow/pcwl_utils.py +384 -0
  360. pandaserver/workflow/psnakemake_container.json +68 -0
  361. pandaserver/workflow/psnakemake_task.json +62 -0
  362. pandaserver/workflow/psnakemake_test.py +60 -0
  363. pandaserver/workflow/snakeparser/__init__.py +3 -0
  364. pandaserver/workflow/snakeparser/extensions.py +74 -0
  365. pandaserver/workflow/snakeparser/log.py +53 -0
  366. pandaserver/workflow/snakeparser/names.py +3 -0
  367. pandaserver/workflow/snakeparser/parser.py +332 -0
  368. pandaserver/workflow/snakeparser/utils.py +29 -0
  369. pandaserver/workflow/step_handler_plugins/base_step_handler.py +85 -0
  370. pandaserver/workflow/step_handler_plugins/panda_task_step_handler.py +280 -0
  371. pandaserver/workflow/workflow_base.py +531 -0
  372. pandaserver/workflow/workflow_core.py +1974 -0
  373. pandaserver/workflow/workflow_core_smoketest.py +388 -0
  374. pandaserver/workflow/workflow_parser.py +222 -0
  375. pandaserver/workflow/workflow_utils.py +1047 -0
@@ -0,0 +1,134 @@
1
+ import json
2
+
3
+ from pandacommon.pandalogger import logger_utils
4
+
5
+ from pandajedi.jedimsgprocessor.base_msg_processor import BaseMsgProcPlugin
6
+
7
+ base_logger = logger_utils.setup_logger(__name__.split(".")[-1])
8
+
9
+
10
+ # processing message processing plugin
11
+ class ProcessingMsgProcPlugin(BaseMsgProcPlugin):
12
+ def process(self, msg_obj, decoded_data=None):
13
+ tmp_log = logger_utils.make_logger(base_logger, token=self.get_pid(), method_name="process")
14
+ # start
15
+ tmp_log.info("start")
16
+ tmp_log.debug(f"sub_id={msg_obj.sub_id} ; msg_id={msg_obj.msg_id}")
17
+ # parse
18
+ if decoded_data is None:
19
+ # json decode
20
+ try:
21
+ msg_dict = json.loads(msg_obj.data)
22
+ except Exception as e:
23
+ err_str = f"failed to parse message json {msg_obj.data} , skipped. {e.__class__.__name__} : {e}"
24
+ tmp_log.error(err_str)
25
+ raise
26
+ else:
27
+ msg_dict = decoded_data
28
+ # sanity check
29
+ try:
30
+ jeditaskid = int(msg_dict["workload_id"])
31
+ # message type
32
+ msg_type = msg_dict["msg_type"]
33
+ if msg_type == "file_processing":
34
+ target_list = msg_dict["files"]
35
+ elif msg_type == "collection_processing":
36
+ target_list = msg_dict["collections"]
37
+ elif msg_type == "work_processing":
38
+ pass
39
+ else:
40
+ raise ValueError(f"invalid msg_type value: {msg_type}")
41
+ # relation type
42
+ relation_type = msg_dict.get("relation_type")
43
+ except Exception as e:
44
+ err_str = f"failed to parse message object dict {msg_dict} , skipped. {e.__class__.__name__} : {e}"
45
+ tmp_log.error(err_str)
46
+ raise
47
+ # run
48
+ try:
49
+ # initialize to_proceed
50
+ to_proceed = False
51
+ # type filters
52
+ if msg_type in ["file_processing", "collection_processing"] and relation_type in ["input"]:
53
+ to_proceed = True
54
+ # whether to proceed the targets
55
+ if to_proceed:
56
+ # initialize
57
+ scope_name_dict_map = {}
58
+ missing_files_dict = {}
59
+ # loop over targets
60
+ for target in target_list:
61
+ name = target["name"]
62
+ scope = target["scope"]
63
+ datasetid = target.get("external_coll_id", None)
64
+ fileid = target.get("external_content_id", None)
65
+ if (msg_type == "file_processing" and target["status"] in ["Available"]) or (
66
+ msg_type == "collection_processing" and target["status"] in ["Closed"]
67
+ ):
68
+ scope_name_dict_map.setdefault(scope, {})
69
+ scope_name_dict_map[scope][name] = (datasetid, fileid)
70
+ elif msg_type == "file_processing" and target["status"] in ["Missing"]:
71
+ # missing files
72
+ missing_files_dict[name] = (datasetid, fileid)
73
+ else:
74
+ # got target in bad attributes, do nothing
75
+ tmp_log.debug(f"jeditaskid={jeditaskid}, scope={scope}, msg_type={msg_type}, status={target['status']}, did nothing for bad target")
76
+ pass
77
+ # run by each scope
78
+ for scope, name_dict in scope_name_dict_map.items():
79
+ # about files or datasets in good status
80
+ if msg_type == "file_processing":
81
+ tmp_log.debug(f"jeditaskid={jeditaskid}, scope={scope}, update about files...")
82
+ res = self.tbIF.updateInputFilesStaged_JEDI(jeditaskid, scope, name_dict, by="iDDS")
83
+ if res is None:
84
+ # got error and rollback in dbproxy
85
+ err_str = f"jeditaskid={jeditaskid}, scope={scope}, failed to update files"
86
+ raise RuntimeError(err_str)
87
+ tmp_log.info(f"jeditaskid={jeditaskid}, scope={scope}, updated {res} files")
88
+ elif msg_type == "collection_processing":
89
+ tmp_log.debug(f"jeditaskid={jeditaskid}, scope={scope}, update about datasets...")
90
+ res = self.tbIF.updateInputDatasetsStaged_JEDI(jeditaskid, scope, name_dict, by="iDDS")
91
+ if res is None:
92
+ # got error and rollback in dbproxy
93
+ err_str = f"jeditaskid={jeditaskid}, scope={scope}, failed to update datasets"
94
+ raise RuntimeError(err_str)
95
+ tmp_log.info(f"jeditaskid={jeditaskid}, scope={scope}, updated {res} datasets")
96
+ # send message to contents feeder if new files are staged
97
+ if res > 0 or msg_type == "collection_processing":
98
+ tmp_s, task_spec = self.tbIF.getTaskWithID_JEDI(jeditaskid)
99
+ if tmp_s and task_spec.is_msg_driven():
100
+ push_ret = self.tbIF.push_task_trigger_message("jedi_contents_feeder", jeditaskid, task_spec=task_spec)
101
+ if push_ret:
102
+ tmp_log.debug(f"pushed trigger message to jedi_contents_feeder for jeditaskid={jeditaskid}")
103
+ else:
104
+ tmp_log.warning(f"failed to push trigger message to jedi_contents_feeder for jeditaskid={jeditaskid}")
105
+ # check if all ok
106
+ if res == len(target_list):
107
+ tmp_log.debug(f"jeditaskid={jeditaskid}, scope={scope}, all OK")
108
+ elif res < len(target_list):
109
+ tmp_log.warning(f"jeditaskid={jeditaskid}, scope={scope}, only {res} out of {len(target_list)} done...")
110
+ elif res > len(target_list):
111
+ tmp_log.warning(f"jeditaskid={jeditaskid}, scope={scope}, strangely, {res} out of {len(target_list)} done...")
112
+ else:
113
+ tmp_log.warning(f"jeditaskid={jeditaskid}, scope={scope}, something unwanted happened...")
114
+ # handle missing files
115
+ n_missing = len(missing_files_dict)
116
+ if n_missing > 0:
117
+ res = self.tbIF.setMissingFilesAboutIdds_JEDI(jeditaskid=jeditaskid, filenames_dict=missing_files_dict)
118
+ if res == n_missing:
119
+ tmp_log.debug(f"jeditaskid={jeditaskid}, marked all {n_missing} files missing")
120
+ elif res < n_missing:
121
+ tmp_log.warning(f"jeditaskid={jeditaskid}, only {res} out of {n_missing} files marked missing...")
122
+ elif res > n_missing:
123
+ tmp_log.warning(f"jeditaskid={jeditaskid}, strangely, {res} out of {n_missing} files marked missing...")
124
+ else:
125
+ tmp_log.warning(f"jeditaskid={jeditaskid}, res={res}, something unwanted happened about missing files...")
126
+ else:
127
+ # do nothing
128
+ tmp_log.debug(f"jeditaskid={jeditaskid}, msg_type={msg_type}, relation_type={relation_type}, nothing done")
129
+ except Exception as e:
130
+ err_str = f"failed to process the message, skipped. {e.__class__.__name__} : {e}"
131
+ tmp_log.error(err_str)
132
+ raise
133
+ # done
134
+ tmp_log.info("done")
@@ -0,0 +1,129 @@
1
+ import copy
2
+ import json
3
+ import re
4
+ import traceback
5
+
6
+ from pandacommon.pandalogger import logger_utils
7
+
8
+ from pandajedi.jediconfig import jedi_config
9
+ from pandajedi.jedimsgprocessor.base_msg_processor import BaseMsgProcPlugin
10
+
11
+ base_logger = logger_utils.setup_logger(__name__.split(".")[-1])
12
+
13
+
14
+ # list of task statuses to return to iDDS
15
+ to_return_task_status_list = [
16
+ "defined",
17
+ "ready",
18
+ "scouting",
19
+ "pending",
20
+ "paused",
21
+ "running",
22
+ "prepared",
23
+ "done",
24
+ "finished",
25
+ "failed",
26
+ "broken",
27
+ "aborted",
28
+ ]
29
+
30
+ to_return_job_status_list = [
31
+ "pending",
32
+ "defined",
33
+ "assigned",
34
+ "activated",
35
+ "starting",
36
+ "running",
37
+ "throttled",
38
+ "finished",
39
+ "failed",
40
+ "cancelled",
41
+ "closed",
42
+ ]
43
+
44
+
45
+ # status report message processing plugin
46
+ class StatusReportMsgProcPlugin(BaseMsgProcPlugin):
47
+ """
48
+ Messaging status of jobs and tasks
49
+ Forward the incoming message to other msg_processors plugin (e.g. Kafka) if configured in params
50
+ Return the processed message to send to iDDS via MQ
51
+ """
52
+
53
+ def initialize(self):
54
+ BaseMsgProcPlugin.initialize(self)
55
+ # forwarding plugins: incoming message will be forwarded to process method of these plugins
56
+ self.forwarding_plugins = []
57
+ forwarding_plugin_names = self.params.get("forwarding_plugins", [])
58
+ if "kafka" in forwarding_plugin_names:
59
+ # Kafka
60
+ from pandajedi.jedimsgprocessor.kafka_msg_processor import (
61
+ KafkaMsgProcPlugin,
62
+ )
63
+
64
+ plugin_inst = KafkaMsgProcPlugin()
65
+ plugin_inst.initialize()
66
+ self.forwarding_plugins.append(plugin_inst)
67
+
68
+ def process(self, msg_obj):
69
+ tmp_log = logger_utils.make_logger(base_logger, token=self.get_pid(), method_name="process")
70
+ # start
71
+ tmp_log.info("start")
72
+ tmp_log.debug(f"sub_id={msg_obj.sub_id} ; msg_id={msg_obj.msg_id}")
73
+ # parse json
74
+ try:
75
+ msg_dict = json.loads(msg_obj.data)
76
+ except Exception as exc:
77
+ err_str = f"failed to parse message json {msg_obj.data} , skipped. {exc.__class__.__name__} : {exc} ; {traceback.format_exc()}"
78
+ tmp_log.error(err_str)
79
+ raise
80
+ # sanity check
81
+ try:
82
+ msg_type = msg_dict["msg_type"]
83
+ except Exception as e:
84
+ err_str = f"failed to parse message object dict {msg_dict} , skipped. {exc.__class__.__name__} : {exc} ; {traceback.format_exc()}"
85
+ tmp_log.error(err_str)
86
+ raise
87
+ # whether to return the message
88
+ to_return_message = False
89
+ # run different plugins according to message type
90
+ try:
91
+ # DB source name from DB schema
92
+ db_source_name = re.sub("_PANDA", "", jedi_config.db.schemaJEDI).lower()
93
+ # process according to msg_type
94
+ if msg_type == "task_status":
95
+ tmp_log.debug("task_status")
96
+ # forwarding
97
+ for plugin_inst in self.forwarding_plugins:
98
+ try:
99
+ tmp_msg_dict = copy.deepcopy(msg_dict)
100
+ tmp_msg_dict["db_source"] = db_source_name
101
+ plugin_inst.process(msg_obj, decoded_data=tmp_msg_dict)
102
+ except Exception as exc:
103
+ tmp_log.error(f"failed to process message object dict {tmp_msg_dict}; {exc.__class__.__name__} : {exc} ; {traceback.format_exc()}")
104
+ # only return certain statuses
105
+ if msg_dict.get("status") in to_return_task_status_list:
106
+ to_return_message = True
107
+ elif msg_type == "job_status":
108
+ tmp_log.debug("job_status")
109
+ # forwarding
110
+ for plugin_inst in self.forwarding_plugins:
111
+ try:
112
+ tmp_msg_dict = copy.deepcopy(msg_dict)
113
+ tmp_msg_dict["db_source"] = db_source_name
114
+ plugin_inst.process(msg_obj, decoded_data=tmp_msg_dict)
115
+ except Exception as exc:
116
+ tmp_log.error(f"failed to process message object dict {tmp_msg_dict}; {exc.__class__.__name__} : {exc} ; {traceback.format_exc()}")
117
+ # only return certain statuses
118
+ if msg_dict.get("status") in to_return_job_status_list:
119
+ to_return_message = True
120
+ else:
121
+ warn_str = f"unknown msg_type : {msg_type}"
122
+ tmp_log.warning(warn_str)
123
+ except Exception:
124
+ raise
125
+ # done
126
+ tmp_log.debug(f"{msg_dict}; to_return={to_return_message}")
127
+ tmp_log.info("done")
128
+ if to_return_message:
129
+ return msg_obj.data
@@ -0,0 +1,118 @@
1
+ import json
2
+
3
+ from pandacommon.pandalogger import logger_utils
4
+
5
+ from pandajedi.jedimsgprocessor.base_msg_processor import BaseMsgProcPlugin
6
+
7
+ base_logger = logger_utils.setup_logger(__name__.split(".")[-1])
8
+
9
+
10
+ # Tape carousel message processing plugin
11
+ class TapeCarouselMsgProcPlugin(BaseMsgProcPlugin):
12
+ def process(self, msg_obj, decoded_data=None):
13
+ tmp_log = logger_utils.make_logger(base_logger, token=self.get_pid(), method_name="process")
14
+ # start
15
+ tmp_log.info("start")
16
+ tmp_log.debug(f"sub_id={msg_obj.sub_id} ; msg_id={msg_obj.msg_id}")
17
+ # parse
18
+ if decoded_data is None:
19
+ # json decode
20
+ try:
21
+ msg_dict = json.loads(msg_obj.data)
22
+ except Exception as e:
23
+ err_str = f"failed to parse message json {msg_obj.data} , skipped. {e.__class__.__name__} : {e}"
24
+ tmp_log.error(err_str)
25
+ raise
26
+ else:
27
+ msg_dict = decoded_data
28
+ # sanity check
29
+ try:
30
+ jeditaskid = int(msg_dict["workload_id"])
31
+ # message type
32
+ msg_type = msg_dict["msg_type"]
33
+ if msg_type == "file_stagein":
34
+ target_list = msg_dict["files"]
35
+ elif msg_type == "collection_stagein":
36
+ target_list = msg_dict["collections"]
37
+ elif msg_type == "work_stagein":
38
+ pass
39
+ else:
40
+ raise ValueError(f"invalid msg_type value: {msg_type}")
41
+ # relation type
42
+ relation_type = msg_dict.get("relation_type")
43
+ except Exception as e:
44
+ err_str = f"failed to parse message object dict {msg_dict} , skipped. {e.__class__.__name__} : {e}"
45
+ tmp_log.error(err_str)
46
+ raise
47
+ # run
48
+ try:
49
+ # initialize to_proceed
50
+ to_proceed = False
51
+ # type filters
52
+ if msg_type in ["file_stagein", "collection_stagein"] and relation_type in ["output"]:
53
+ to_proceed = True
54
+ # whether to proceed the targets
55
+ if to_proceed:
56
+ # map
57
+ scope_name_dict_map = {}
58
+ # loop over targets
59
+ for target in target_list:
60
+ name = target["name"]
61
+ scope = target["scope"]
62
+ datasetid = target.get("external_coll_id", None)
63
+ fileid = target.get("external_content_id", None)
64
+ if (msg_type == "file_stagein" and target["status"] in ["Available"]) or (
65
+ msg_type == "collection_stagein" and target["status"] in ["Closed"]
66
+ ):
67
+ scope_name_dict_map.setdefault(scope, {})
68
+ scope_name_dict_map[scope][name] = (datasetid, fileid)
69
+ else:
70
+ # got target in bad attributes, do nothing
71
+ tmp_log.debug(f"jeditaskid={jeditaskid}, scope={scope}, msg_type={msg_type}, status={target['status']}, did nothing for bad target")
72
+ pass
73
+ # run by each scope
74
+ for scope, name_dict in scope_name_dict_map.items():
75
+ # about files or datasets in good status
76
+ if msg_type == "file_stagein":
77
+ tmp_log.debug(f"jeditaskid={jeditaskid}, scope={scope}, update about files...")
78
+ res = self.tbIF.updateInputFilesStaged_JEDI(jeditaskid, scope, name_dict, by="iDDS")
79
+ if res is None:
80
+ # got error and rollback in dbproxy
81
+ err_str = f"jeditaskid={jeditaskid}, scope={scope}, failed to update files"
82
+ raise RuntimeError(err_str)
83
+ tmp_log.info(f"jeditaskid={jeditaskid}, scope={scope}, updated {res} files")
84
+ elif msg_type == "collection_stagein":
85
+ tmp_log.debug(f"jeditaskid={jeditaskid}, scope={scope}, update about datasets...")
86
+ res = self.tbIF.updateInputDatasetsStaged_JEDI(jeditaskid, scope, name_dict, by="iDDS")
87
+ if res is None:
88
+ # got error and rollback in dbproxy
89
+ err_str = f"jeditaskid={jeditaskid}, scope={scope}, failed to update datasets"
90
+ raise RuntimeError(err_str)
91
+ tmp_log.info(f"jeditaskid={jeditaskid}, scope={scope}, updated {res} datasets")
92
+ # send message to contents feeder if new files are staged
93
+ if res > 0 or msg_type == "collection_stagein":
94
+ tmp_s, task_spec = self.tbIF.getTaskWithID_JEDI(jeditaskid)
95
+ if tmp_s and task_spec.is_msg_driven():
96
+ push_ret = self.tbIF.push_task_trigger_message("jedi_contents_feeder", jeditaskid, task_spec=task_spec)
97
+ if push_ret:
98
+ tmp_log.debug(f"pushed trigger message to jedi_contents_feeder for jeditaskid={jeditaskid}")
99
+ else:
100
+ tmp_log.warning(f"failed to push trigger message to jedi_contents_feeder for jeditaskid={jeditaskid}")
101
+ # check if all ok
102
+ if res == len(target_list):
103
+ tmp_log.debug(f"jeditaskid={jeditaskid}, scope={scope}, all OK")
104
+ elif res < len(target_list):
105
+ tmp_log.warning(f"jeditaskid={jeditaskid}, scope={scope}, only {res} out of {len(target_list)} done...")
106
+ elif res > len(target_list):
107
+ tmp_log.warning(f"jeditaskid={jeditaskid}, scope={scope}, strangely, {res} out of {len(target_list)} done...")
108
+ else:
109
+ tmp_log.warning(f"jeditaskid={jeditaskid}, scope={scope}, something unwanted happened...")
110
+ else:
111
+ # do nothing
112
+ tmp_log.debug(f"jeditaskid={jeditaskid}, msg_type={msg_type}, relation_type={relation_type}, nothing done")
113
+ except Exception as e:
114
+ err_str = f"failed to process the message, skipped. {e.__class__.__name__} : {e}"
115
+ tmp_log.error(err_str)
116
+ raise
117
+ # done
118
+ tmp_log.info("done")
@@ -0,0 +1,89 @@
1
+ import json
2
+
3
+ from pandacommon.pandalogger import logger_utils
4
+
5
+ from pandajedi.jedimsgprocessor.base_msg_processor import BaseMsgProcPlugin
6
+ from pandaserver.workflow.workflow_core import WorkflowInterface
7
+
8
+ base_logger = logger_utils.setup_logger(__name__.split(".")[-1])
9
+
10
+
11
+ # Workflow manager message processor plugin
12
+ class WorkflowManagerMsgProcPlugin(BaseMsgProcPlugin):
13
+ """
14
+ Message-driven workflow manager
15
+ """
16
+
17
+ def initialize(self):
18
+ """
19
+ Initialize the plugin
20
+ """
21
+ BaseMsgProcPlugin.initialize(self)
22
+ self.workflow_interface = WorkflowInterface(self.tbIF)
23
+
24
+ def process(self, msg_obj):
25
+ """
26
+ Process the message
27
+ Typical message data looks like:
28
+ {"msg_type":"workflow", "workflow_id": 123, "timestamp": 987654321}
29
+ {"msg_type":"wfstep", "step_id": 456, "timestamp": 987654321}
30
+ {"msg_type":"wfdata", "data_id": 789, "timestamp": 987654321}
31
+
32
+ Args:
33
+ msg_obj: message object
34
+ """
35
+ tmp_log = logger_utils.make_logger(base_logger, token=self.get_pid(), method_name="process")
36
+ # start
37
+ tmp_log.info("start")
38
+ tmp_log.debug(f"sub_id={msg_obj.sub_id} ; msg_id={msg_obj.msg_id}")
39
+ # parse json
40
+ try:
41
+ msg_dict = json.loads(msg_obj.data)
42
+ except Exception as e:
43
+ err_str = f"failed to parse message json {msg_obj.data} , skipped. {e.__class__.__name__} : {e}"
44
+ tmp_log.error(err_str)
45
+ raise
46
+ # sanity check
47
+ try:
48
+ msg_type = msg_dict["msg_type"]
49
+ except Exception as e:
50
+ err_str = f"failed to parse message object dict {msg_dict} , skipped. {e.__class__.__name__} : {e}"
51
+ tmp_log.error(err_str)
52
+ raise
53
+ if msg_type not in ("workflow", "wfstep", "wfdata"):
54
+ err_str = f"got unknown msg_type {msg_type} , skipped "
55
+ tmp_log.error(err_str)
56
+ raise
57
+ # run
58
+ try:
59
+ tmp_log.info(f"got message {msg_dict}")
60
+ if msg_type == "workflow":
61
+ workflow_id = msg_dict["workflow_id"]
62
+ workflow_spec = self.tbIF.get_workflow(workflow_id)
63
+ if workflow_spec is None:
64
+ tmp_log.warning(f"workflow_id={workflow_id} not found; skipped")
65
+ return
66
+ stats, workflow_spec = self.workflow_interface.process_workflow(workflow_spec, by="msg")
67
+ tmp_log.info(f"processed workflow_id={workflow_id}")
68
+ elif msg_type == "wfstep":
69
+ step_id = msg_dict["step_id"]
70
+ step_spec = self.tbIF.get_workflow_step(step_id)
71
+ if step_spec is None:
72
+ tmp_log.warning(f"step_id={step_id} not found; skipped")
73
+ return
74
+ stats, step_spec = self.workflow_interface.process_step(step_spec, by="msg")
75
+ tmp_log.info(f"processed step_id={step_id}")
76
+ elif msg_type == "wfdata":
77
+ data_id = msg_dict["data_id"]
78
+ data_spec = self.tbIF.get_workflow_data(data_id)
79
+ if data_spec is None:
80
+ tmp_log.warning(f"data_id={data_id} not found; skipped")
81
+ return
82
+ stats, data_spec = self.workflow_interface.process_data(data_spec, by="msg")
83
+ tmp_log.info(f"processed data_id={data_id}")
84
+ except Exception as e:
85
+ err_str = f"failed to run, skipped. {e.__class__.__name__} : {e}"
86
+ tmp_log.error(err_str)
87
+ raise
88
+ # done
89
+ tmp_log.info("done")