tasker-engine 1.0.0

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 (605) hide show
  1. checksums.yaml +7 -0
  2. data/LICENSE +22 -0
  3. data/README.md +443 -0
  4. data/Rakefile +10 -0
  5. data/app/controllers/tasker/analytics_controller.rb +179 -0
  6. data/app/controllers/tasker/application_controller.rb +45 -0
  7. data/app/controllers/tasker/graphql_controller.rb +193 -0
  8. data/app/controllers/tasker/handlers_controller.rb +217 -0
  9. data/app/controllers/tasker/health_controller.rb +229 -0
  10. data/app/controllers/tasker/metrics_controller.rb +111 -0
  11. data/app/controllers/tasker/page_sort.rb +97 -0
  12. data/app/controllers/tasker/task_diagrams_controller.rb +30 -0
  13. data/app/controllers/tasker/tasks_controller.rb +123 -0
  14. data/app/controllers/tasker/workflow_steps_controller.rb +69 -0
  15. data/app/graphql/examples/all_tasks.graphql +22 -0
  16. data/app/graphql/examples/pending_tasks.graphql +23 -0
  17. data/app/graphql/tasker/graph_ql_types/annotation_type.rb +14 -0
  18. data/app/graphql/tasker/graph_ql_types/base_argument.rb +9 -0
  19. data/app/graphql/tasker/graph_ql_types/base_connection.rb +11 -0
  20. data/app/graphql/tasker/graph_ql_types/base_edge.rb +10 -0
  21. data/app/graphql/tasker/graph_ql_types/base_enum.rb +9 -0
  22. data/app/graphql/tasker/graph_ql_types/base_field.rb +10 -0
  23. data/app/graphql/tasker/graph_ql_types/base_input_object.rb +10 -0
  24. data/app/graphql/tasker/graph_ql_types/base_interface.rb +14 -0
  25. data/app/graphql/tasker/graph_ql_types/base_object.rb +10 -0
  26. data/app/graphql/tasker/graph_ql_types/base_scalar.rb +9 -0
  27. data/app/graphql/tasker/graph_ql_types/base_union.rb +11 -0
  28. data/app/graphql/tasker/graph_ql_types/dependent_system_object_map_type.rb +18 -0
  29. data/app/graphql/tasker/graph_ql_types/dependent_system_type.rb +13 -0
  30. data/app/graphql/tasker/graph_ql_types/mutation_type.rb +16 -0
  31. data/app/graphql/tasker/graph_ql_types/named_step_type.rb +16 -0
  32. data/app/graphql/tasker/graph_ql_types/named_task_type.rb +14 -0
  33. data/app/graphql/tasker/graph_ql_types/named_tasks_named_step_type.rb +19 -0
  34. data/app/graphql/tasker/graph_ql_types/node_type.rb +12 -0
  35. data/app/graphql/tasker/graph_ql_types/query_type.rb +20 -0
  36. data/app/graphql/tasker/graph_ql_types/task_annotation_type.rb +17 -0
  37. data/app/graphql/tasker/graph_ql_types/task_interface.rb +17 -0
  38. data/app/graphql/tasker/graph_ql_types/task_type.rb +26 -0
  39. data/app/graphql/tasker/graph_ql_types/workflow_step_type.rb +154 -0
  40. data/app/graphql/tasker/graph_ql_types.rb +42 -0
  41. data/app/graphql/tasker/mutations/base_mutation.rb +13 -0
  42. data/app/graphql/tasker/mutations/cancel_step.rb +29 -0
  43. data/app/graphql/tasker/mutations/cancel_task.rb +29 -0
  44. data/app/graphql/tasker/mutations/create_task.rb +52 -0
  45. data/app/graphql/tasker/mutations/update_step.rb +36 -0
  46. data/app/graphql/tasker/mutations/update_task.rb +41 -0
  47. data/app/graphql/tasker/queries/all_annotation_types.rb +17 -0
  48. data/app/graphql/tasker/queries/all_tasks.rb +23 -0
  49. data/app/graphql/tasker/queries/base_query.rb +9 -0
  50. data/app/graphql/tasker/queries/helpers.rb +16 -0
  51. data/app/graphql/tasker/queries/one_step.rb +24 -0
  52. data/app/graphql/tasker/queries/one_task.rb +18 -0
  53. data/app/graphql/tasker/queries/tasks_by_annotation.rb +31 -0
  54. data/app/graphql/tasker/queries/tasks_by_status.rb +30 -0
  55. data/app/graphql/tasker/tasker_rails_schema.rb +52 -0
  56. data/app/jobs/tasker/application_job.rb +8 -0
  57. data/app/jobs/tasker/metrics_export_job.rb +252 -0
  58. data/app/jobs/tasker/task_runner_job.rb +224 -0
  59. data/app/models/tasker/annotation_type.rb +26 -0
  60. data/app/models/tasker/application_record.rb +70 -0
  61. data/app/models/tasker/dependent_system.rb +26 -0
  62. data/app/models/tasker/dependent_system_object_map.rb +64 -0
  63. data/app/models/tasker/diagram/edge.rb +106 -0
  64. data/app/models/tasker/diagram/flowchart.rb +137 -0
  65. data/app/models/tasker/diagram/node.rb +99 -0
  66. data/app/models/tasker/named_step.rb +41 -0
  67. data/app/models/tasker/named_task.rb +121 -0
  68. data/app/models/tasker/named_tasks_named_step.rb +82 -0
  69. data/app/models/tasker/step_dag_relationship.rb +65 -0
  70. data/app/models/tasker/step_readiness_status.rb +59 -0
  71. data/app/models/tasker/task.rb +424 -0
  72. data/app/models/tasker/task_annotation.rb +36 -0
  73. data/app/models/tasker/task_diagram.rb +332 -0
  74. data/app/models/tasker/task_execution_context.rb +29 -0
  75. data/app/models/tasker/task_namespace.rb +41 -0
  76. data/app/models/tasker/task_transition.rb +235 -0
  77. data/app/models/tasker/workflow_step.rb +461 -0
  78. data/app/models/tasker/workflow_step_edge.rb +94 -0
  79. data/app/models/tasker/workflow_step_transition.rb +434 -0
  80. data/app/serializers/tasker/annotation_type_serializer.rb +8 -0
  81. data/app/serializers/tasker/handler_serializer.rb +109 -0
  82. data/app/serializers/tasker/task_annotation_serializer.rb +32 -0
  83. data/app/serializers/tasker/task_serializer.rb +168 -0
  84. data/app/serializers/tasker/workflow_step_serializer.rb +27 -0
  85. data/app/services/tasker/analytics_service.rb +409 -0
  86. data/app/views/tasker/task/_diagram.html.erb +32 -0
  87. data/config/initializers/dry_struct.rb +11 -0
  88. data/config/initializers/statesman.rb +6 -0
  89. data/config/initializers/tasker_orchestration.rb +17 -0
  90. data/config/initializers/time_formats.rb +4 -0
  91. data/config/routes.rb +34 -0
  92. data/config/tasker/subscriptions/example_integrations.yml +67 -0
  93. data/config/tasker/system_events.yml +305 -0
  94. data/db/functions/calculate_dependency_levels_v01.sql +45 -0
  95. data/db/functions/get_analytics_metrics_v01.sql +137 -0
  96. data/db/functions/get_slowest_steps_v01.sql +82 -0
  97. data/db/functions/get_slowest_tasks_v01.sql +96 -0
  98. data/db/functions/get_step_readiness_status_batch_v01.sql +140 -0
  99. data/db/functions/get_step_readiness_status_v01.sql +139 -0
  100. data/db/functions/get_system_health_counts_v01.sql +108 -0
  101. data/db/functions/get_task_execution_context_v01.sql +108 -0
  102. data/db/functions/get_task_execution_contexts_batch_v01.sql +104 -0
  103. data/db/init/schema.sql +2277 -0
  104. data/db/migrate/20250701165431_initial_tasker_schema.rb +116 -0
  105. data/db/views/tasker_step_dag_relationships_v01.sql +69 -0
  106. data/docs/APPLICATION_GENERATOR.md +384 -0
  107. data/docs/AUTH.md +1780 -0
  108. data/docs/CIRCUIT_BREAKER.md +224 -0
  109. data/docs/DEVELOPER_GUIDE.md +2665 -0
  110. data/docs/EVENT_SYSTEM.md +637 -0
  111. data/docs/EXECUTION_CONFIGURATION.md +341 -0
  112. data/docs/FLOW_CHART.md +149 -0
  113. data/docs/HEALTH.md +542 -0
  114. data/docs/METRICS.md +731 -0
  115. data/docs/OPTIMIZATION_PLAN.md +1479 -0
  116. data/docs/OVERVIEW.md +552 -0
  117. data/docs/QUICK_START.md +270 -0
  118. data/docs/REGISTRY_SYSTEMS.md +373 -0
  119. data/docs/REST_API.md +632 -0
  120. data/docs/ROADMAP.md +221 -0
  121. data/docs/SQL_FUNCTIONS.md +1408 -0
  122. data/docs/TASK_DIAGRAM.md +252 -0
  123. data/docs/TASK_EXECUTION_CONTROL_FLOW.md +237 -0
  124. data/docs/TELEMETRY.md +795 -0
  125. data/docs/TROUBLESHOOTING.md +756 -0
  126. data/docs/TaskHandlerGenerator.html +255 -0
  127. data/docs/Tasker/Analysis/RuntimeGraphAnalyzer.html +907 -0
  128. data/docs/Tasker/Analysis/TemplateGraphAnalyzer.html +1236 -0
  129. data/docs/Tasker/Analysis.html +117 -0
  130. data/docs/Tasker/AnalyticsController.html +450 -0
  131. data/docs/Tasker/AnalyticsService/BottleneckAnalytics.html +816 -0
  132. data/docs/Tasker/AnalyticsService/PerformanceAnalytics.html +586 -0
  133. data/docs/Tasker/AnalyticsService.html +2221 -0
  134. data/docs/Tasker/AnnotationType.html +137 -0
  135. data/docs/Tasker/AnnotationTypeSerializer.html +124 -0
  136. data/docs/Tasker/ApplicationController.html +147 -0
  137. data/docs/Tasker/ApplicationJob.html +128 -0
  138. data/docs/Tasker/ApplicationRecord.html +378 -0
  139. data/docs/Tasker/Authentication/AuthenticationError.html +124 -0
  140. data/docs/Tasker/Authentication/ConfigurationError.html +124 -0
  141. data/docs/Tasker/Authentication/Coordinator.html +242 -0
  142. data/docs/Tasker/Authentication/Interface.html +560 -0
  143. data/docs/Tasker/Authentication/InterfaceError.html +124 -0
  144. data/docs/Tasker/Authentication/NoneAuthenticator.html +338 -0
  145. data/docs/Tasker/Authentication.html +119 -0
  146. data/docs/Tasker/Authorization/AuthorizationError.html +139 -0
  147. data/docs/Tasker/Authorization/BaseCoordinator.html +927 -0
  148. data/docs/Tasker/Authorization/ConfigurationError.html +153 -0
  149. data/docs/Tasker/Authorization/ResourceConstants/ACTIONS.html +428 -0
  150. data/docs/Tasker/Authorization/ResourceConstants/RESOURCES.html +365 -0
  151. data/docs/Tasker/Authorization/ResourceConstants.html +146 -0
  152. data/docs/Tasker/Authorization/ResourceRegistry.html +882 -0
  153. data/docs/Tasker/Authorization/UnauthorizedError.html +153 -0
  154. data/docs/Tasker/Authorization.html +582 -0
  155. data/docs/Tasker/CacheCapabilities.html +167 -0
  156. data/docs/Tasker/CacheStrategy.html +1297 -0
  157. data/docs/Tasker/Concerns/Authenticatable.html +116 -0
  158. data/docs/Tasker/Concerns/Authorizable/AdminStatusChecker.html +256 -0
  159. data/docs/Tasker/Concerns/Authorizable.html +816 -0
  160. data/docs/Tasker/Concerns/ControllerAuthorizable.html +157 -0
  161. data/docs/Tasker/Concerns/EventPublisher.html +4023 -0
  162. data/docs/Tasker/Concerns/IdempotentStateTransitions.html +806 -0
  163. data/docs/Tasker/Concerns/LifecycleEventHelpers.html +129 -0
  164. data/docs/Tasker/Concerns/OrchestrationPublisher.html +129 -0
  165. data/docs/Tasker/Concerns/StateMachineBase/ClassMethods.html +1075 -0
  166. data/docs/Tasker/Concerns/StateMachineBase/StateMachineBase/ClassMethods.html +191 -0
  167. data/docs/Tasker/Concerns/StateMachineBase/StateMachineBase.html +126 -0
  168. data/docs/Tasker/Concerns/StateMachineBase.html +153 -0
  169. data/docs/Tasker/Concerns/StructuredLogging.html +1413 -0
  170. data/docs/Tasker/Concerns.html +117 -0
  171. data/docs/Tasker/Configuration/AuthConfiguration.html +1023 -0
  172. data/docs/Tasker/Configuration/ConfigurationProxy.html +581 -0
  173. data/docs/Tasker/Configuration/DatabaseConfiguration.html +475 -0
  174. data/docs/Tasker/Configuration/EngineConfiguration.html +1265 -0
  175. data/docs/Tasker/Configuration/HealthConfiguration.html +791 -0
  176. data/docs/Tasker/Configuration/TelemetryConfiguration.html +1308 -0
  177. data/docs/Tasker/Configuration/TelemetryConfigurationProxy.html +388 -0
  178. data/docs/Tasker/Configuration.html +1669 -0
  179. data/docs/Tasker/ConfigurationError.html +143 -0
  180. data/docs/Tasker/ConfiguredTask.html +514 -0
  181. data/docs/Tasker/Constants/EventDefinitions.html +590 -0
  182. data/docs/Tasker/Constants/LifecycleEvents.html +137 -0
  183. data/docs/Tasker/Constants/ObservabilityEvents/Step.html +152 -0
  184. data/docs/Tasker/Constants/ObservabilityEvents/Task.html +142 -0
  185. data/docs/Tasker/Constants/ObservabilityEvents.html +126 -0
  186. data/docs/Tasker/Constants/RegistryEvents.html +285 -0
  187. data/docs/Tasker/Constants/StepEvents.html +177 -0
  188. data/docs/Tasker/Constants/TaskEvents.html +167 -0
  189. data/docs/Tasker/Constants/TaskExecution/ExecutionStatus.html +207 -0
  190. data/docs/Tasker/Constants/TaskExecution/HealthStatus.html +191 -0
  191. data/docs/Tasker/Constants/TaskExecution/RecommendedAction.html +207 -0
  192. data/docs/Tasker/Constants/TaskExecution.html +126 -0
  193. data/docs/Tasker/Constants/TaskFinalization/ErrorMessages.html +132 -0
  194. data/docs/Tasker/Constants/TaskFinalization/PendingReasons.html +207 -0
  195. data/docs/Tasker/Constants/TaskFinalization/ReenqueueReasons.html +239 -0
  196. data/docs/Tasker/Constants/TaskFinalization.html +126 -0
  197. data/docs/Tasker/Constants/TaskStatuses.html +223 -0
  198. data/docs/Tasker/Constants/TestEvents.html +163 -0
  199. data/docs/Tasker/Constants/WorkflowEvents.html +222 -0
  200. data/docs/Tasker/Constants/WorkflowStepStatuses.html +223 -0
  201. data/docs/Tasker/Constants.html +561 -0
  202. data/docs/Tasker/DependentSystem.html +137 -0
  203. data/docs/Tasker/DependentSystemObjectMap.html +250 -0
  204. data/docs/Tasker/DetectorRegistry.html +598 -0
  205. data/docs/Tasker/Diagram/Edge.html +1191 -0
  206. data/docs/Tasker/Diagram/Flowchart.html +1539 -0
  207. data/docs/Tasker/Diagram/Node.html +1165 -0
  208. data/docs/Tasker/Diagram.html +117 -0
  209. data/docs/Tasker/Engine.html +215 -0
  210. data/docs/Tasker/Error.html +139 -0
  211. data/docs/Tasker/Events/Bus.html +1226 -0
  212. data/docs/Tasker/Events/Catalog/CatalogPrinter.html +258 -0
  213. data/docs/Tasker/Events/Catalog/CustomEventRegistrar.html +276 -0
  214. data/docs/Tasker/Events/Catalog/ExamplePayloadGenerator.html +294 -0
  215. data/docs/Tasker/Events/Catalog.html +1291 -0
  216. data/docs/Tasker/Events/CustomRegistry.html +943 -0
  217. data/docs/Tasker/Events/DefinitionLoader.html +575 -0
  218. data/docs/Tasker/Events/EventPayloadBuilder/ErrorInfoExtractor.html +286 -0
  219. data/docs/Tasker/Events/EventPayloadBuilder/StepPayloadBuilder.html +312 -0
  220. data/docs/Tasker/Events/EventPayloadBuilder.html +664 -0
  221. data/docs/Tasker/Events/Publisher.html +365 -0
  222. data/docs/Tasker/Events/Subscribers/BaseSubscriber/ErrorCategorizer/ErrorTypeClassifier.html +1128 -0
  223. data/docs/Tasker/Events/Subscribers/BaseSubscriber/ErrorCategorizer.html +270 -0
  224. data/docs/Tasker/Events/Subscribers/BaseSubscriber/MetricTagsExtractor.html +266 -0
  225. data/docs/Tasker/Events/Subscribers/BaseSubscriber.html +2556 -0
  226. data/docs/Tasker/Events/Subscribers/MetricsSubscriber.html +723 -0
  227. data/docs/Tasker/Events/Subscribers/TelemetrySubscriber.html +2251 -0
  228. data/docs/Tasker/Events/Subscribers.html +117 -0
  229. data/docs/Tasker/Events/SubscriptionLoader.html +493 -0
  230. data/docs/Tasker/Events.html +294 -0
  231. data/docs/Tasker/EventsGenerator.html +459 -0
  232. data/docs/Tasker/Functions/FunctionBasedAnalyticsMetrics/AnalyticsMetrics.html +135 -0
  233. data/docs/Tasker/Functions/FunctionBasedAnalyticsMetrics.html +412 -0
  234. data/docs/Tasker/Functions/FunctionBasedDependencyLevels.html +598 -0
  235. data/docs/Tasker/Functions/FunctionBasedSlowestSteps/SlowestStep.html +135 -0
  236. data/docs/Tasker/Functions/FunctionBasedSlowestSteps.html +453 -0
  237. data/docs/Tasker/Functions/FunctionBasedSlowestTasks/SlowestTask.html +135 -0
  238. data/docs/Tasker/Functions/FunctionBasedSlowestTasks.html +453 -0
  239. data/docs/Tasker/Functions/FunctionBasedStepReadinessStatus.html +1457 -0
  240. data/docs/Tasker/Functions/FunctionBasedSystemHealthCounts/HealthMetrics.html +135 -0
  241. data/docs/Tasker/Functions/FunctionBasedSystemHealthCounts.html +370 -0
  242. data/docs/Tasker/Functions/FunctionBasedTaskExecutionContext.html +1250 -0
  243. data/docs/Tasker/Functions/FunctionWrapper.html +479 -0
  244. data/docs/Tasker/Functions.html +117 -0
  245. data/docs/Tasker/Generators/AuthenticatorGenerator/UsageInstructionsFormatter.html +244 -0
  246. data/docs/Tasker/Generators/AuthenticatorGenerator.html +373 -0
  247. data/docs/Tasker/Generators/AuthorizationCoordinatorGenerator.html +430 -0
  248. data/docs/Tasker/Generators/SubscriberGenerator.html +377 -0
  249. data/docs/Tasker/Generators/TaskHandlerGenerator.html +263 -0
  250. data/docs/Tasker/Generators.html +117 -0
  251. data/docs/Tasker/GraphQLTypes/AnnotationType.html +132 -0
  252. data/docs/Tasker/GraphQLTypes/BaseArgument.html +124 -0
  253. data/docs/Tasker/GraphQLTypes/BaseConnection.html +124 -0
  254. data/docs/Tasker/GraphQLTypes/BaseEdge.html +130 -0
  255. data/docs/Tasker/GraphQLTypes/BaseEnum.html +124 -0
  256. data/docs/Tasker/GraphQLTypes/BaseField.html +124 -0
  257. data/docs/Tasker/GraphQLTypes/BaseInputObject.html +124 -0
  258. data/docs/Tasker/GraphQLTypes/BaseInterface.html +116 -0
  259. data/docs/Tasker/GraphQLTypes/BaseObject.html +128 -0
  260. data/docs/Tasker/GraphQLTypes/BaseScalar.html +124 -0
  261. data/docs/Tasker/GraphQLTypes/BaseUnion.html +124 -0
  262. data/docs/Tasker/GraphQLTypes/DependentSystemObjectMapType.html +132 -0
  263. data/docs/Tasker/GraphQLTypes/DependentSystemType.html +132 -0
  264. data/docs/Tasker/GraphQLTypes/MutationType.html +132 -0
  265. data/docs/Tasker/GraphQLTypes/NamedStepType.html +132 -0
  266. data/docs/Tasker/GraphQLTypes/NamedTaskType.html +132 -0
  267. data/docs/Tasker/GraphQLTypes/NamedTasksNamedStepType.html +132 -0
  268. data/docs/Tasker/GraphQLTypes/NodeType.html +118 -0
  269. data/docs/Tasker/GraphQLTypes/QueryType.html +139 -0
  270. data/docs/Tasker/GraphQLTypes/TaskAnnotationType.html +132 -0
  271. data/docs/Tasker/GraphQLTypes/TaskInterface.html +111 -0
  272. data/docs/Tasker/GraphQLTypes/TaskType.html +201 -0
  273. data/docs/Tasker/GraphQLTypes/WorkflowStepType.html +694 -0
  274. data/docs/Tasker/GraphQLTypes.html +130 -0
  275. data/docs/Tasker/GraphqlController.html +251 -0
  276. data/docs/Tasker/HandlerFactory.html +1518 -0
  277. data/docs/Tasker/HandlerSerializer.html +682 -0
  278. data/docs/Tasker/HandlersController.html +574 -0
  279. data/docs/Tasker/HashIdentityStrategy.html +278 -0
  280. data/docs/Tasker/Health/ReadinessChecker.html +712 -0
  281. data/docs/Tasker/Health/StatusChecker.html +653 -0
  282. data/docs/Tasker/Health.html +117 -0
  283. data/docs/Tasker/HealthController.html +523 -0
  284. data/docs/Tasker/IdentityStrategy.html +276 -0
  285. data/docs/Tasker/InvalidTaskHandlerConfig.html +135 -0
  286. data/docs/Tasker/LifecycleEvents/Events/Step.html +162 -0
  287. data/docs/Tasker/LifecycleEvents/Events/Task.html +162 -0
  288. data/docs/Tasker/LifecycleEvents/Events.html +204 -0
  289. data/docs/Tasker/LifecycleEvents/Publisher.html +132 -0
  290. data/docs/Tasker/LifecycleEvents.html +799 -0
  291. data/docs/Tasker/Logging/CorrelationIdGenerator.html +688 -0
  292. data/docs/Tasker/Logging.html +115 -0
  293. data/docs/Tasker/MetricsController.html +293 -0
  294. data/docs/Tasker/MetricsExportJob.html +414 -0
  295. data/docs/Tasker/Mutations/BaseMutation.html +128 -0
  296. data/docs/Tasker/Mutations/CancelStep.html +219 -0
  297. data/docs/Tasker/Mutations/CancelTask.html +221 -0
  298. data/docs/Tasker/Mutations/CreateTask.html +243 -0
  299. data/docs/Tasker/Mutations/UpdateStep.html +243 -0
  300. data/docs/Tasker/Mutations/UpdateTask.html +243 -0
  301. data/docs/Tasker/Mutations.html +117 -0
  302. data/docs/Tasker/NamedStep.html +216 -0
  303. data/docs/Tasker/NamedTask.html +910 -0
  304. data/docs/Tasker/NamedTasksNamedStep.html +435 -0
  305. data/docs/Tasker/Orchestration/BackoffCalculator.html +404 -0
  306. data/docs/Tasker/Orchestration/ConnectionBuilder/ConfigValidator.html +258 -0
  307. data/docs/Tasker/Orchestration/ConnectionBuilder.html +435 -0
  308. data/docs/Tasker/Orchestration/ConnectionPoolIntelligence.html +513 -0
  309. data/docs/Tasker/Orchestration/Coordinator.html +641 -0
  310. data/docs/Tasker/Orchestration/FutureStateAnalyzer.html +1045 -0
  311. data/docs/Tasker/Orchestration/Orchestrator.html +679 -0
  312. data/docs/Tasker/Orchestration/PluginIntegration.html +1127 -0
  313. data/docs/Tasker/Orchestration/ResponseProcessor.html +504 -0
  314. data/docs/Tasker/Orchestration/RetryHeaderParser.html +304 -0
  315. data/docs/Tasker/Orchestration/StepExecutor.html +995 -0
  316. data/docs/Tasker/Orchestration/StepSequenceFactory.html +644 -0
  317. data/docs/Tasker/Orchestration/TaskFinalizer/BlockageChecker.html +264 -0
  318. data/docs/Tasker/Orchestration/TaskFinalizer/ContextManager.html +254 -0
  319. data/docs/Tasker/Orchestration/TaskFinalizer/DelayCalculator.html +556 -0
  320. data/docs/Tasker/Orchestration/TaskFinalizer/FinalizationDecisionMaker.html +348 -0
  321. data/docs/Tasker/Orchestration/TaskFinalizer/FinalizationProcessor.html +286 -0
  322. data/docs/Tasker/Orchestration/TaskFinalizer/ReasonDeterminer.html +432 -0
  323. data/docs/Tasker/Orchestration/TaskFinalizer/ReenqueueManager.html +296 -0
  324. data/docs/Tasker/Orchestration/TaskFinalizer/UnclearStateHandler.html +314 -0
  325. data/docs/Tasker/Orchestration/TaskFinalizer.html +1212 -0
  326. data/docs/Tasker/Orchestration/TaskInitializer.html +766 -0
  327. data/docs/Tasker/Orchestration/TaskReenqueuer.html +506 -0
  328. data/docs/Tasker/Orchestration/ViableStepDiscovery.html +442 -0
  329. data/docs/Tasker/Orchestration/WorkflowCoordinator.html +510 -0
  330. data/docs/Tasker/Orchestration.html +130 -0
  331. data/docs/Tasker/PageSort/PageSortParamsBuilder.html +296 -0
  332. data/docs/Tasker/PageSort.html +247 -0
  333. data/docs/Tasker/PermanentError.html +518 -0
  334. data/docs/Tasker/ProceduralError.html +147 -0
  335. data/docs/Tasker/Queries/AllAnnotationTypes.html +217 -0
  336. data/docs/Tasker/Queries/AllTasks.html +221 -0
  337. data/docs/Tasker/Queries/BaseQuery.html +128 -0
  338. data/docs/Tasker/Queries/Helpers.html +187 -0
  339. data/docs/Tasker/Queries/OneStep.html +225 -0
  340. data/docs/Tasker/Queries/OneTask.html +217 -0
  341. data/docs/Tasker/Queries/TasksByAnnotation.html +231 -0
  342. data/docs/Tasker/Queries/TasksByStatus.html +233 -0
  343. data/docs/Tasker/Queries.html +119 -0
  344. data/docs/Tasker/Railtie.html +124 -0
  345. data/docs/Tasker/Registry/BaseRegistry.html +1690 -0
  346. data/docs/Tasker/Registry/EventPublisher.html +667 -0
  347. data/docs/Tasker/Registry/InterfaceValidator.html +569 -0
  348. data/docs/Tasker/Registry/RegistrationError.html +132 -0
  349. data/docs/Tasker/Registry/RegistryError.html +139 -0
  350. data/docs/Tasker/Registry/StatisticsCollector.html +841 -0
  351. data/docs/Tasker/Registry/SubscriberRegistry.html +1504 -0
  352. data/docs/Tasker/Registry/ValidationError.html +132 -0
  353. data/docs/Tasker/Registry.html +119 -0
  354. data/docs/Tasker/RetryableError.html +515 -0
  355. data/docs/Tasker/StateMachine/Compatibility.html +282 -0
  356. data/docs/Tasker/StateMachine/InvalidStateTransition.html +135 -0
  357. data/docs/Tasker/StateMachine/StepStateMachine/StandardizedPayloadBuilder.html +260 -0
  358. data/docs/Tasker/StateMachine/StepStateMachine.html +2215 -0
  359. data/docs/Tasker/StateMachine/TaskStateMachine.html +734 -0
  360. data/docs/Tasker/StateMachine.html +602 -0
  361. data/docs/Tasker/StepDagRelationship.html +657 -0
  362. data/docs/Tasker/StepHandler/Api/Config.html +1091 -0
  363. data/docs/Tasker/StepHandler/Api.html +884 -0
  364. data/docs/Tasker/StepHandler/AutomaticEventPublishing.html +321 -0
  365. data/docs/Tasker/StepHandler/Base.html +970 -0
  366. data/docs/Tasker/StepHandler.html +119 -0
  367. data/docs/Tasker/StepReadinessStatus.html +836 -0
  368. data/docs/Tasker/Task.html +2575 -0
  369. data/docs/Tasker/TaskAnnotation.html +137 -0
  370. data/docs/Tasker/TaskAnnotationSerializer.html +124 -0
  371. data/docs/Tasker/TaskBuilder/StepNameValidator.html +264 -0
  372. data/docs/Tasker/TaskBuilder/StepTemplateDefiner.html +264 -0
  373. data/docs/Tasker/TaskBuilder.html +764 -0
  374. data/docs/Tasker/TaskDiagram/StepToStepEdgeBuilder.html +260 -0
  375. data/docs/Tasker/TaskDiagram/TaskToRootStepEdgeBuilder.html +290 -0
  376. data/docs/Tasker/TaskDiagram.html +548 -0
  377. data/docs/Tasker/TaskDiagramsController.html +240 -0
  378. data/docs/Tasker/TaskExecutionContext.html +469 -0
  379. data/docs/Tasker/TaskHandler/ClassMethods/StepTemplateDefiner/ClassBasedEventRegistrar.html +238 -0
  380. data/docs/Tasker/TaskHandler/ClassMethods/StepTemplateDefiner/YamlEventRegistrar.html +254 -0
  381. data/docs/Tasker/TaskHandler/ClassMethods/StepTemplateDefiner.html +988 -0
  382. data/docs/Tasker/TaskHandler/ClassMethods.html +357 -0
  383. data/docs/Tasker/TaskHandler/InstanceMethods.html +1396 -0
  384. data/docs/Tasker/TaskHandler/StepGroup.html +1748 -0
  385. data/docs/Tasker/TaskHandler.html +271 -0
  386. data/docs/Tasker/TaskNamespace.html +312 -0
  387. data/docs/Tasker/TaskRunnerJob.html +406 -0
  388. data/docs/Tasker/TaskSerializer.html +474 -0
  389. data/docs/Tasker/TaskTransition.html +1517 -0
  390. data/docs/Tasker/TaskWorkflowSummary.html +988 -0
  391. data/docs/Tasker/TaskerRailsSchema/InvalidObjectTypeError.html +132 -0
  392. data/docs/Tasker/TaskerRailsSchema/TypeResolutionError.html +139 -0
  393. data/docs/Tasker/TaskerRailsSchema/UnknownInterfaceError.html +132 -0
  394. data/docs/Tasker/TaskerRailsSchema.html +384 -0
  395. data/docs/Tasker/TasksController.html +595 -0
  396. data/docs/Tasker/Telemetry/EventMapping.html +1307 -0
  397. data/docs/Tasker/Telemetry/EventRouter.html +2178 -0
  398. data/docs/Tasker/Telemetry/Events/ExportEvents.html +246 -0
  399. data/docs/Tasker/Telemetry/Events.html +115 -0
  400. data/docs/Tasker/Telemetry/ExportCoordinator/DistributedLockTimeoutError.html +135 -0
  401. data/docs/Tasker/Telemetry/ExportCoordinator.html +2137 -0
  402. data/docs/Tasker/Telemetry/IntelligentCacheManager.html +1083 -0
  403. data/docs/Tasker/Telemetry/LogBackend.html +1088 -0
  404. data/docs/Tasker/Telemetry/MetricTypes/Counter.html +1054 -0
  405. data/docs/Tasker/Telemetry/MetricTypes/Gauge.html +1270 -0
  406. data/docs/Tasker/Telemetry/MetricTypes/Histogram.html +1492 -0
  407. data/docs/Tasker/Telemetry/MetricTypes.html +153 -0
  408. data/docs/Tasker/Telemetry/MetricsBackend.html +2510 -0
  409. data/docs/Tasker/Telemetry/MetricsExportService.html +578 -0
  410. data/docs/Tasker/Telemetry/PluginRegistry.html +1774 -0
  411. data/docs/Tasker/Telemetry/Plugins/BaseExporter.html +1835 -0
  412. data/docs/Tasker/Telemetry/Plugins/CsvExporter.html +768 -0
  413. data/docs/Tasker/Telemetry/Plugins/JsonExporter.html +747 -0
  414. data/docs/Tasker/Telemetry/Plugins.html +117 -0
  415. data/docs/Tasker/Telemetry/PrometheusExporter.html +481 -0
  416. data/docs/Tasker/Telemetry/TraceBackend.html +891 -0
  417. data/docs/Tasker/Telemetry.html +130 -0
  418. data/docs/Tasker/Types/AuthConfig.html +886 -0
  419. data/docs/Tasker/Types/BackoffConfig.html +1063 -0
  420. data/docs/Tasker/Types/BaseConfig.html +227 -0
  421. data/docs/Tasker/Types/CacheConfig.html +1731 -0
  422. data/docs/Tasker/Types/DatabaseConfig.html +388 -0
  423. data/docs/Tasker/Types/DependencyGraph.html +526 -0
  424. data/docs/Tasker/Types/DependencyGraphConfig.html +753 -0
  425. data/docs/Tasker/Types/EngineConfig.html +1181 -0
  426. data/docs/Tasker/Types/ExecutionConfig.html +1963 -0
  427. data/docs/Tasker/Types/GraphEdge.html +517 -0
  428. data/docs/Tasker/Types/GraphMetadata.html +781 -0
  429. data/docs/Tasker/Types/GraphNode.html +694 -0
  430. data/docs/Tasker/Types/HealthConfig.html +784 -0
  431. data/docs/Tasker/Types/StepSequence.html +353 -0
  432. data/docs/Tasker/Types/StepTemplate.html +1193 -0
  433. data/docs/Tasker/Types/TaskRequest.html +1179 -0
  434. data/docs/Tasker/Types/TelemetryConfig.html +2746 -0
  435. data/docs/Tasker/Types.html +154 -0
  436. data/docs/Tasker/WorkflowStep/StepFinder.html +282 -0
  437. data/docs/Tasker/WorkflowStep.html +2724 -0
  438. data/docs/Tasker/WorkflowStepEdge.html +304 -0
  439. data/docs/Tasker/WorkflowStepSerializer.html +305 -0
  440. data/docs/Tasker/WorkflowStepTransition/TransitionDescriptionFormatter.html +282 -0
  441. data/docs/Tasker/WorkflowStepTransition.html +2201 -0
  442. data/docs/Tasker/WorkflowStepsController.html +462 -0
  443. data/docs/Tasker.html +452 -0
  444. data/docs/VISION.md +584 -0
  445. data/docs/WHY.md +21 -0
  446. data/docs/_index.html +2375 -0
  447. data/docs/class_list.html +54 -0
  448. data/docs/css/common.css +1 -0
  449. data/docs/css/full_list.css +58 -0
  450. data/docs/css/style.css +503 -0
  451. data/docs/events/migration_plan_outcomes.md +80 -0
  452. data/docs/file.README.html +541 -0
  453. data/docs/file_list.html +59 -0
  454. data/docs/frames.html +22 -0
  455. data/docs/index.html +541 -0
  456. data/docs/js/app.js +344 -0
  457. data/docs/js/full_list.js +242 -0
  458. data/docs/js/jquery.js +4 -0
  459. data/docs/method_list.html +9182 -0
  460. data/docs/top-level-namespace.html +110 -0
  461. data/lib/generators/tasker/authenticator_generator.rb +301 -0
  462. data/lib/generators/tasker/authorization_coordinator_generator.rb +139 -0
  463. data/lib/generators/tasker/events_generator.rb +91 -0
  464. data/lib/generators/tasker/subscriber_generator.rb +107 -0
  465. data/lib/generators/tasker/task_handler_generator.rb +138 -0
  466. data/lib/generators/tasker/templates/api_token_authenticator.rb.erb +113 -0
  467. data/lib/generators/tasker/templates/api_token_authenticator_spec.rb.erb +144 -0
  468. data/lib/generators/tasker/templates/authorization_coordinator.rb.erb +95 -0
  469. data/lib/generators/tasker/templates/authorization_coordinator_spec.rb.erb +142 -0
  470. data/lib/generators/tasker/templates/custom_authenticator.rb.erb +108 -0
  471. data/lib/generators/tasker/templates/custom_authenticator_spec.rb.erb +162 -0
  472. data/lib/generators/tasker/templates/custom_events.yml.erb +62 -0
  473. data/lib/generators/tasker/templates/custom_subscriber.rb.erb +72 -0
  474. data/lib/generators/tasker/templates/devise_authenticator.rb.erb +101 -0
  475. data/lib/generators/tasker/templates/devise_authenticator_spec.rb.erb +126 -0
  476. data/lib/generators/tasker/templates/initialize.rb.erb +202 -0
  477. data/lib/generators/tasker/templates/jwt_authenticator.rb.erb +144 -0
  478. data/lib/generators/tasker/templates/jwt_authenticator_spec.rb.erb +298 -0
  479. data/lib/generators/tasker/templates/metrics_subscriber.rb.erb +258 -0
  480. data/lib/generators/tasker/templates/metrics_subscriber_spec.rb.erb +308 -0
  481. data/lib/generators/tasker/templates/omniauth_authenticator.rb.erb +135 -0
  482. data/lib/generators/tasker/templates/omniauth_authenticator_spec.rb.erb +196 -0
  483. data/lib/generators/tasker/templates/opentelemetry_initializer.rb +52 -0
  484. data/lib/generators/tasker/templates/subscriber.rb.erb +64 -0
  485. data/lib/generators/tasker/templates/subscriber_spec.rb.erb +80 -0
  486. data/lib/generators/tasker/templates/task_config.yaml.erb +117 -0
  487. data/lib/generators/tasker/templates/task_handler.rb.erb +59 -0
  488. data/lib/generators/tasker/templates/task_handler_spec.rb.erb +159 -0
  489. data/lib/tasker/analysis/runtime_graph_analyzer.rb +1168 -0
  490. data/lib/tasker/analysis/template_graph_analyzer.rb +328 -0
  491. data/lib/tasker/authentication/coordinator.rb +78 -0
  492. data/lib/tasker/authentication/errors.rb +9 -0
  493. data/lib/tasker/authentication/interface.rb +36 -0
  494. data/lib/tasker/authentication/none_authenticator.rb +26 -0
  495. data/lib/tasker/authorization/base_coordinator.rb +112 -0
  496. data/lib/tasker/authorization/errors.rb +26 -0
  497. data/lib/tasker/authorization/resource_constants.rb +74 -0
  498. data/lib/tasker/authorization/resource_registry.rb +143 -0
  499. data/lib/tasker/authorization.rb +75 -0
  500. data/lib/tasker/cache_capabilities.rb +131 -0
  501. data/lib/tasker/cache_strategy.rb +469 -0
  502. data/lib/tasker/concerns/authenticatable.rb +41 -0
  503. data/lib/tasker/concerns/authorizable.rb +204 -0
  504. data/lib/tasker/concerns/controller_authorizable.rb +124 -0
  505. data/lib/tasker/concerns/event_publisher.rb +716 -0
  506. data/lib/tasker/concerns/idempotent_state_transitions.rb +128 -0
  507. data/lib/tasker/concerns/state_machine_base.rb +218 -0
  508. data/lib/tasker/concerns/structured_logging.rb +387 -0
  509. data/lib/tasker/configuration.rb +325 -0
  510. data/lib/tasker/constants/event_definitions.rb +147 -0
  511. data/lib/tasker/constants/registry_events.rb +54 -0
  512. data/lib/tasker/constants.rb +417 -0
  513. data/lib/tasker/engine.rb +90 -0
  514. data/lib/tasker/errors.rb +90 -0
  515. data/lib/tasker/events/catalog.rb +432 -0
  516. data/lib/tasker/events/custom_registry.rb +175 -0
  517. data/lib/tasker/events/definition_loader.rb +199 -0
  518. data/lib/tasker/events/event_payload_builder.rb +461 -0
  519. data/lib/tasker/events/publisher.rb +149 -0
  520. data/lib/tasker/events/subscribers/base_subscriber.rb +601 -0
  521. data/lib/tasker/events/subscribers/metrics_subscriber.rb +120 -0
  522. data/lib/tasker/events/subscribers/telemetry_subscriber.rb +462 -0
  523. data/lib/tasker/events/subscription_loader.rb +161 -0
  524. data/lib/tasker/events.rb +37 -0
  525. data/lib/tasker/functions/function_based_analytics_metrics.rb +103 -0
  526. data/lib/tasker/functions/function_based_dependency_levels.rb +54 -0
  527. data/lib/tasker/functions/function_based_slowest_steps.rb +84 -0
  528. data/lib/tasker/functions/function_based_slowest_tasks.rb +84 -0
  529. data/lib/tasker/functions/function_based_step_readiness_status.rb +183 -0
  530. data/lib/tasker/functions/function_based_system_health_counts.rb +94 -0
  531. data/lib/tasker/functions/function_based_task_execution_context.rb +148 -0
  532. data/lib/tasker/functions/function_wrapper.rb +42 -0
  533. data/lib/tasker/functions.rb +12 -0
  534. data/lib/tasker/handler_factory.rb +322 -0
  535. data/lib/tasker/health/readiness_checker.rb +186 -0
  536. data/lib/tasker/health/status_checker.rb +203 -0
  537. data/lib/tasker/identity_strategy.rb +38 -0
  538. data/lib/tasker/logging/correlation_id_generator.rb +120 -0
  539. data/lib/tasker/orchestration/backoff_calculator.rb +184 -0
  540. data/lib/tasker/orchestration/connection_builder.rb +122 -0
  541. data/lib/tasker/orchestration/connection_pool_intelligence.rb +177 -0
  542. data/lib/tasker/orchestration/coordinator.rb +119 -0
  543. data/lib/tasker/orchestration/future_state_analyzer.rb +137 -0
  544. data/lib/tasker/orchestration/plugin_integration.rb +124 -0
  545. data/lib/tasker/orchestration/response_processor.rb +168 -0
  546. data/lib/tasker/orchestration/retry_header_parser.rb +78 -0
  547. data/lib/tasker/orchestration/step_executor.rb +941 -0
  548. data/lib/tasker/orchestration/step_sequence_factory.rb +67 -0
  549. data/lib/tasker/orchestration/task_finalizer.rb +564 -0
  550. data/lib/tasker/orchestration/task_initializer.rb +140 -0
  551. data/lib/tasker/orchestration/task_reenqueuer.rb +71 -0
  552. data/lib/tasker/orchestration/viable_step_discovery.rb +65 -0
  553. data/lib/tasker/orchestration/workflow_coordinator.rb +294 -0
  554. data/lib/tasker/orchestration.rb +45 -0
  555. data/lib/tasker/railtie.rb +9 -0
  556. data/lib/tasker/registry/base_registry.rb +177 -0
  557. data/lib/tasker/registry/event_publisher.rb +91 -0
  558. data/lib/tasker/registry/interface_validator.rb +140 -0
  559. data/lib/tasker/registry/statistics_collector.rb +381 -0
  560. data/lib/tasker/registry/subscriber_registry.rb +285 -0
  561. data/lib/tasker/registry.rb +22 -0
  562. data/lib/tasker/state_machine/step_state_machine.rb +508 -0
  563. data/lib/tasker/state_machine/task_state_machine.rb +192 -0
  564. data/lib/tasker/state_machine.rb +83 -0
  565. data/lib/tasker/step_handler/api.rb +410 -0
  566. data/lib/tasker/step_handler/base.rb +206 -0
  567. data/lib/tasker/task_builder.rb +432 -0
  568. data/lib/tasker/task_handler/class_methods.rb +324 -0
  569. data/lib/tasker/task_handler/instance_methods.rb +293 -0
  570. data/lib/tasker/task_handler/step_group.rb +182 -0
  571. data/lib/tasker/task_handler.rb +43 -0
  572. data/lib/tasker/telemetry/event_mapping.rb +126 -0
  573. data/lib/tasker/telemetry/event_router.rb +318 -0
  574. data/lib/tasker/telemetry/events/export_events.rb +38 -0
  575. data/lib/tasker/telemetry/export_coordinator.rb +497 -0
  576. data/lib/tasker/telemetry/intelligent_cache_manager.rb +508 -0
  577. data/lib/tasker/telemetry/log_backend.rb +224 -0
  578. data/lib/tasker/telemetry/metric_types.rb +368 -0
  579. data/lib/tasker/telemetry/metrics_backend.rb +1227 -0
  580. data/lib/tasker/telemetry/metrics_export_service.rb +392 -0
  581. data/lib/tasker/telemetry/plugin_registry.rb +333 -0
  582. data/lib/tasker/telemetry/plugins/base_exporter.rb +246 -0
  583. data/lib/tasker/telemetry/plugins/csv_exporter.rb +198 -0
  584. data/lib/tasker/telemetry/plugins/json_exporter.rb +141 -0
  585. data/lib/tasker/telemetry/prometheus_exporter.rb +249 -0
  586. data/lib/tasker/telemetry/trace_backend.rb +186 -0
  587. data/lib/tasker/telemetry.rb +59 -0
  588. data/lib/tasker/types/auth_config.rb +81 -0
  589. data/lib/tasker/types/backoff_config.rb +142 -0
  590. data/lib/tasker/types/cache_config.rb +257 -0
  591. data/lib/tasker/types/database_config.rb +39 -0
  592. data/lib/tasker/types/dependency_graph.rb +225 -0
  593. data/lib/tasker/types/dependency_graph_config.rb +149 -0
  594. data/lib/tasker/types/engine_config.rb +131 -0
  595. data/lib/tasker/types/execution_config.rb +289 -0
  596. data/lib/tasker/types/health_config.rb +84 -0
  597. data/lib/tasker/types/step_sequence.rb +24 -0
  598. data/lib/tasker/types/step_template.rb +63 -0
  599. data/lib/tasker/types/task_request.rb +60 -0
  600. data/lib/tasker/types/telemetry_config.rb +273 -0
  601. data/lib/tasker/types.rb +64 -0
  602. data/lib/tasker/version.rb +7 -0
  603. data/lib/tasker.rb +82 -0
  604. data/lib/tasks/tasker_tasks.rake +302 -0
  605. metadata +958 -0
@@ -0,0 +1,96 @@
1
+ -- Slowest Tasks Analysis Function
2
+ -- Returns the slowest tasks within a specified time period with performance metrics
3
+ -- Input: since_timestamp, limit_count, and optional namespace/name/version filters
4
+ -- Output: Ranked list of slowest tasks with duration and context
5
+
6
+ CREATE OR REPLACE FUNCTION get_slowest_tasks_v01(
7
+ since_timestamp TIMESTAMPTZ DEFAULT NULL,
8
+ limit_count INTEGER DEFAULT 10,
9
+ namespace_filter TEXT DEFAULT NULL,
10
+ task_name_filter TEXT DEFAULT NULL,
11
+ version_filter TEXT DEFAULT NULL
12
+ )
13
+ RETURNS TABLE (
14
+ task_id BIGINT,
15
+ task_name VARCHAR(64),
16
+ namespace_name VARCHAR(64),
17
+ version VARCHAR(64),
18
+ duration_seconds NUMERIC(10,3),
19
+ step_count BIGINT,
20
+ completed_steps BIGINT,
21
+ error_steps BIGINT,
22
+ created_at TIMESTAMPTZ,
23
+ completed_at TIMESTAMPTZ,
24
+ initiator VARCHAR(128),
25
+ source_system VARCHAR(128)
26
+ ) LANGUAGE plpgsql STABLE AS $$
27
+ DECLARE
28
+ analysis_start TIMESTAMPTZ;
29
+ BEGIN
30
+ -- Set analysis start time (default to 24 hours ago if not provided)
31
+ analysis_start := COALESCE(since_timestamp, NOW() - INTERVAL '24 hours');
32
+
33
+ RETURN QUERY
34
+ WITH task_durations AS (
35
+ SELECT
36
+ t.task_id,
37
+ nt.name as task_name,
38
+ tn.name as namespace_name,
39
+ nt.version,
40
+ t.created_at,
41
+ t.initiator,
42
+ t.source_system,
43
+ -- Find the latest completion time across all steps
44
+ MAX(wst.created_at) FILTER (
45
+ WHERE wst.to_state IN ('complete', 'error') AND wst.most_recent = true
46
+ ) as latest_completion,
47
+ -- Calculate duration from task creation to latest step completion
48
+ EXTRACT(EPOCH FROM (
49
+ MAX(wst.created_at) FILTER (
50
+ WHERE wst.to_state IN ('complete', 'error') AND wst.most_recent = true
51
+ ) - t.created_at
52
+ )) as duration_seconds,
53
+ COUNT(ws.workflow_step_id) as total_steps,
54
+ COUNT(ws.workflow_step_id) FILTER (
55
+ WHERE complete_wst.to_state = 'complete' AND complete_wst.most_recent = true
56
+ ) as completed_step_count,
57
+ COUNT(ws.workflow_step_id) FILTER (
58
+ WHERE error_wst.to_state = 'error' AND error_wst.most_recent = true
59
+ ) as error_step_count
60
+ FROM tasker_tasks t
61
+ INNER JOIN tasker_named_tasks nt ON nt.named_task_id = t.named_task_id
62
+ INNER JOIN tasker_task_namespaces tn ON tn.task_namespace_id = nt.task_namespace_id
63
+ INNER JOIN tasker_workflow_steps ws ON ws.task_id = t.task_id
64
+ LEFT JOIN tasker_workflow_step_transitions wst ON wst.workflow_step_id = ws.workflow_step_id
65
+ LEFT JOIN tasker_workflow_step_transitions complete_wst ON complete_wst.workflow_step_id = ws.workflow_step_id
66
+ AND complete_wst.to_state = 'complete' AND complete_wst.most_recent = true
67
+ LEFT JOIN tasker_workflow_step_transitions error_wst ON error_wst.workflow_step_id = ws.workflow_step_id
68
+ AND error_wst.to_state = 'error' AND error_wst.most_recent = true
69
+ WHERE t.created_at > analysis_start
70
+ AND (namespace_filter IS NULL OR tn.name = namespace_filter)
71
+ AND (task_name_filter IS NULL OR nt.name = task_name_filter)
72
+ AND (version_filter IS NULL OR nt.version = version_filter)
73
+ GROUP BY t.task_id, nt.name, tn.name, nt.version, t.created_at, t.initiator, t.source_system
74
+ HAVING MAX(wst.created_at) FILTER (
75
+ WHERE wst.to_state IN ('complete', 'error') AND wst.most_recent = true
76
+ ) IS NOT NULL -- Only include tasks that have at least one completed/failed step
77
+ )
78
+ SELECT
79
+ td.task_id,
80
+ td.task_name,
81
+ td.namespace_name,
82
+ td.version,
83
+ ROUND(td.duration_seconds, 3),
84
+ td.total_steps,
85
+ td.completed_step_count,
86
+ td.error_step_count,
87
+ td.created_at,
88
+ td.latest_completion,
89
+ td.initiator,
90
+ td.source_system
91
+ FROM task_durations td
92
+ WHERE td.duration_seconds IS NOT NULL
93
+ ORDER BY td.duration_seconds DESC
94
+ LIMIT limit_count;
95
+ END;
96
+ $$;
@@ -0,0 +1,140 @@
1
+ -- Batch Step Readiness Status Function
2
+ -- Gets step readiness data for multiple tasks in a single query
3
+ -- Input: Array of task_ids (gets all steps for each task)
4
+ -- Output: Multiple rows with step readiness data, properly grouped by task
5
+
6
+ CREATE OR REPLACE FUNCTION get_step_readiness_status_batch(input_task_ids BIGINT[])
7
+ RETURNS TABLE(
8
+ workflow_step_id BIGINT,
9
+ task_id BIGINT,
10
+ named_step_id INTEGER,
11
+ name TEXT,
12
+ current_state TEXT,
13
+ dependencies_satisfied BOOLEAN,
14
+ retry_eligible BOOLEAN,
15
+ ready_for_execution BOOLEAN,
16
+ last_failure_at TIMESTAMP,
17
+ next_retry_at TIMESTAMP,
18
+ total_parents INTEGER,
19
+ completed_parents INTEGER,
20
+ attempts INTEGER,
21
+ retry_limit INTEGER,
22
+ backoff_request_seconds INTEGER,
23
+ last_attempted_at TIMESTAMP
24
+ ) LANGUAGE plpgsql STABLE AS $$
25
+ BEGIN
26
+ RETURN QUERY
27
+ SELECT
28
+ ws.workflow_step_id,
29
+ ws.task_id,
30
+ ws.named_step_id,
31
+ ns.name::TEXT,
32
+
33
+ -- Current State Information (optimized using most_recent flag)
34
+ COALESCE(current_state.to_state, 'pending')::TEXT as current_state,
35
+
36
+ -- Dependency Analysis (calculated from direct joins)
37
+ CASE
38
+ WHEN dep_edges.to_step_id IS NULL THEN true -- Root steps (no parents)
39
+ WHEN COUNT(dep_edges.from_step_id) = 0 THEN true -- Steps with zero dependencies
40
+ WHEN COUNT(CASE WHEN parent_states.to_state IN ('complete', 'resolved_manually') THEN 1 END) = COUNT(dep_edges.from_step_id) THEN true
41
+ ELSE false
42
+ END as dependencies_satisfied,
43
+
44
+ -- Simplified Retry & Backoff Analysis
45
+ CASE
46
+ WHEN ws.attempts >= COALESCE(ws.retry_limit, 3) THEN false
47
+ WHEN ws.attempts > 0 AND COALESCE(ws.retryable, true) = false THEN false
48
+ WHEN last_failure.created_at IS NULL THEN true
49
+ WHEN ws.backoff_request_seconds IS NOT NULL AND ws.last_attempted_at IS NOT NULL THEN
50
+ ws.last_attempted_at + (ws.backoff_request_seconds * interval '1 second') <= NOW()
51
+ WHEN last_failure.created_at IS NOT NULL THEN
52
+ last_failure.created_at + (
53
+ LEAST(power(2, COALESCE(ws.attempts, 1)) * interval '1 second', interval '30 seconds')
54
+ ) <= NOW()
55
+ ELSE true
56
+ END as retry_eligible,
57
+
58
+ -- Simplified Final Readiness Calculation
59
+ CASE
60
+ WHEN COALESCE(current_state.to_state, 'pending') IN ('pending', 'error')
61
+ AND (ws.processed = false OR ws.processed IS NULL) -- CRITICAL: Only unprocessed steps can be ready
62
+ AND (dep_edges.to_step_id IS NULL OR
63
+ COUNT(dep_edges.from_step_id) = 0 OR
64
+ COUNT(CASE WHEN parent_states.to_state IN ('complete', 'resolved_manually') THEN 1 END) = COUNT(dep_edges.from_step_id))
65
+ AND (ws.attempts < COALESCE(ws.retry_limit, 3))
66
+ AND (COALESCE(ws.retryable, true) = true)
67
+ AND (ws.in_process = false OR ws.in_process IS NULL)
68
+ AND (
69
+ -- Check explicit backoff timing (most restrictive)
70
+ -- If backoff is set, the backoff period must have expired
71
+ CASE
72
+ WHEN ws.backoff_request_seconds IS NOT NULL AND ws.last_attempted_at IS NOT NULL THEN
73
+ ws.last_attempted_at + (ws.backoff_request_seconds * interval '1 second') <= NOW()
74
+ ELSE true -- No explicit backoff set
75
+ END
76
+ AND
77
+ -- Then check failure-based backoff
78
+ (last_failure.created_at IS NULL OR
79
+ last_failure.created_at + (LEAST(power(2, COALESCE(ws.attempts, 1)) * interval '1 second', interval '30 seconds')) <= NOW())
80
+ )
81
+ THEN true
82
+ ELSE false
83
+ END as ready_for_execution,
84
+
85
+ -- Timing Information
86
+ last_failure.created_at as last_failure_at,
87
+ CASE
88
+ WHEN ws.backoff_request_seconds IS NOT NULL AND ws.last_attempted_at IS NOT NULL THEN
89
+ ws.last_attempted_at + (ws.backoff_request_seconds * interval '1 second')
90
+ WHEN last_failure.created_at IS NOT NULL THEN
91
+ last_failure.created_at + (LEAST(power(2, COALESCE(ws.attempts, 1)) * interval '1 second', interval '30 seconds'))
92
+ ELSE NULL
93
+ END as next_retry_at,
94
+
95
+ -- Dependency Context (calculated from joins)
96
+ COALESCE(COUNT(dep_edges.from_step_id), 0)::INTEGER as total_parents,
97
+ COALESCE(COUNT(CASE WHEN parent_states.to_state IN ('complete', 'resolved_manually') THEN 1 END), 0)::INTEGER as completed_parents,
98
+
99
+ -- Retry Context
100
+ ws.attempts,
101
+ COALESCE(ws.retry_limit, 3) as retry_limit,
102
+ ws.backoff_request_seconds,
103
+ ws.last_attempted_at
104
+
105
+ FROM tasker_workflow_steps ws
106
+ JOIN tasker_named_steps ns ON ns.named_step_id = ws.named_step_id
107
+
108
+ -- OPTIMIZED: Current State using most_recent flag instead of DISTINCT ON
109
+ LEFT JOIN tasker_workflow_step_transitions current_state
110
+ ON current_state.workflow_step_id = ws.workflow_step_id
111
+ AND current_state.most_recent = true
112
+
113
+ -- OPTIMIZED: Dependency check using direct joins (no subquery)
114
+ LEFT JOIN tasker_workflow_step_edges dep_edges
115
+ ON dep_edges.to_step_id = ws.workflow_step_id
116
+ LEFT JOIN tasker_workflow_step_transitions parent_states
117
+ ON parent_states.workflow_step_id = dep_edges.from_step_id
118
+ AND parent_states.most_recent = true
119
+
120
+ -- OPTIMIZED: Last failure using index-optimized approach
121
+ LEFT JOIN tasker_workflow_step_transitions last_failure
122
+ ON last_failure.workflow_step_id = ws.workflow_step_id
123
+ AND last_failure.to_state = 'error'
124
+ AND last_failure.most_recent = true
125
+
126
+ -- KEY PERFORMANCE IMPROVEMENT: Filter by multiple tasks at once
127
+ -- CRITICAL FIX: Include ALL steps for task execution context calculation
128
+ -- Only filter by processed status when specifically querying for ready steps
129
+ WHERE ws.task_id = ANY(input_task_ids)
130
+
131
+ GROUP BY
132
+ ws.workflow_step_id, ws.task_id, ws.named_step_id, ns.name,
133
+ current_state.to_state, last_failure.created_at,
134
+ ws.attempts, ws.retry_limit, ws.backoff_request_seconds, ws.last_attempted_at,
135
+ ws.in_process, ws.processed, ws.retryable, dep_edges.to_step_id
136
+
137
+ -- IMPORTANT: Order by task_id, then workflow_step_id for consistent grouping
138
+ ORDER BY ws.task_id, ws.workflow_step_id;
139
+ END;
140
+ $$;
@@ -0,0 +1,139 @@
1
+ -- Step Readiness Status Function
2
+ -- Converts the view logic to a parameterized function for targeted queries
3
+ -- Input: Array of workflow_step_ids
4
+ -- Output: Readiness data for specified steps only
5
+
6
+ CREATE OR REPLACE FUNCTION get_step_readiness_status(input_task_id BIGINT, step_ids BIGINT[] DEFAULT NULL)
7
+ RETURNS TABLE(
8
+ workflow_step_id BIGINT,
9
+ task_id BIGINT,
10
+ named_step_id INTEGER,
11
+ name TEXT,
12
+ current_state TEXT,
13
+ dependencies_satisfied BOOLEAN,
14
+ retry_eligible BOOLEAN,
15
+ ready_for_execution BOOLEAN,
16
+ last_failure_at TIMESTAMP,
17
+ next_retry_at TIMESTAMP,
18
+ total_parents INTEGER,
19
+ completed_parents INTEGER,
20
+ attempts INTEGER,
21
+ retry_limit INTEGER,
22
+ backoff_request_seconds INTEGER,
23
+ last_attempted_at TIMESTAMP
24
+ ) LANGUAGE plpgsql STABLE AS $$
25
+ BEGIN
26
+ RETURN QUERY
27
+ SELECT
28
+ ws.workflow_step_id,
29
+ ws.task_id,
30
+ ws.named_step_id,
31
+ ns.name::TEXT,
32
+
33
+ -- Current State Information (optimized using most_recent flag)
34
+ COALESCE(current_state.to_state, 'pending')::TEXT as current_state,
35
+
36
+ -- Dependency Analysis (calculated from direct joins)
37
+ CASE
38
+ WHEN dep_edges.to_step_id IS NULL THEN true -- Root steps (no parents)
39
+ WHEN COUNT(dep_edges.from_step_id) = 0 THEN true -- Steps with zero dependencies
40
+ WHEN COUNT(CASE WHEN parent_states.to_state IN ('complete', 'resolved_manually') THEN 1 END) = COUNT(dep_edges.from_step_id) THEN true
41
+ ELSE false
42
+ END as dependencies_satisfied,
43
+
44
+ -- Simplified Retry & Backoff Analysis
45
+ CASE
46
+ WHEN ws.attempts >= COALESCE(ws.retry_limit, 3) THEN false
47
+ WHEN ws.attempts > 0 AND COALESCE(ws.retryable, true) = false THEN false
48
+ WHEN last_failure.created_at IS NULL THEN true
49
+ WHEN ws.backoff_request_seconds IS NOT NULL AND ws.last_attempted_at IS NOT NULL THEN
50
+ ws.last_attempted_at + (ws.backoff_request_seconds * interval '1 second') <= NOW()
51
+ WHEN last_failure.created_at IS NOT NULL THEN
52
+ last_failure.created_at + (
53
+ LEAST(power(2, COALESCE(ws.attempts, 1)) * interval '1 second', interval '30 seconds')
54
+ ) <= NOW()
55
+ ELSE true
56
+ END as retry_eligible,
57
+
58
+ -- Simplified Final Readiness Calculation
59
+ CASE
60
+ WHEN COALESCE(current_state.to_state, 'pending') IN ('pending', 'error')
61
+ AND (ws.processed = false OR ws.processed IS NULL) -- CRITICAL: Only unprocessed steps can be ready
62
+ AND (dep_edges.to_step_id IS NULL OR
63
+ COUNT(dep_edges.from_step_id) = 0 OR
64
+ COUNT(CASE WHEN parent_states.to_state IN ('complete', 'resolved_manually') THEN 1 END) = COUNT(dep_edges.from_step_id))
65
+ AND (ws.attempts < COALESCE(ws.retry_limit, 3))
66
+ AND (COALESCE(ws.retryable, true) = true)
67
+ AND (ws.in_process = false OR ws.in_process IS NULL)
68
+ AND (
69
+ -- Check explicit backoff timing (most restrictive)
70
+ -- If backoff is set, the backoff period must have expired
71
+ CASE
72
+ WHEN ws.backoff_request_seconds IS NOT NULL AND ws.last_attempted_at IS NOT NULL THEN
73
+ ws.last_attempted_at + (ws.backoff_request_seconds * interval '1 second') <= NOW()
74
+ ELSE true -- No explicit backoff set
75
+ END
76
+ AND
77
+ -- Then check failure-based backoff
78
+ (last_failure.created_at IS NULL OR
79
+ last_failure.created_at + (LEAST(power(2, COALESCE(ws.attempts, 1)) * interval '1 second', interval '30 seconds')) <= NOW())
80
+ )
81
+ THEN true
82
+ ELSE false
83
+ END as ready_for_execution,
84
+
85
+ -- Timing Information
86
+ last_failure.created_at as last_failure_at,
87
+ CASE
88
+ WHEN ws.backoff_request_seconds IS NOT NULL AND ws.last_attempted_at IS NOT NULL THEN
89
+ ws.last_attempted_at + (ws.backoff_request_seconds * interval '1 second')
90
+ WHEN last_failure.created_at IS NOT NULL THEN
91
+ last_failure.created_at + (LEAST(power(2, COALESCE(ws.attempts, 1)) * interval '1 second', interval '30 seconds'))
92
+ ELSE NULL
93
+ END as next_retry_at,
94
+
95
+ -- Dependency Context (calculated from joins)
96
+ COALESCE(COUNT(dep_edges.from_step_id), 0)::INTEGER as total_parents,
97
+ COALESCE(COUNT(CASE WHEN parent_states.to_state IN ('complete', 'resolved_manually') THEN 1 END), 0)::INTEGER as completed_parents,
98
+
99
+ -- Retry Context
100
+ ws.attempts,
101
+ COALESCE(ws.retry_limit, 3) as retry_limit,
102
+ ws.backoff_request_seconds,
103
+ ws.last_attempted_at
104
+
105
+ FROM tasker_workflow_steps ws
106
+ JOIN tasker_named_steps ns ON ns.named_step_id = ws.named_step_id
107
+
108
+ -- OPTIMIZED: Current State using most_recent flag instead of DISTINCT ON
109
+ LEFT JOIN tasker_workflow_step_transitions current_state
110
+ ON current_state.workflow_step_id = ws.workflow_step_id
111
+ AND current_state.most_recent = true
112
+
113
+ -- OPTIMIZED: Dependency check using direct joins (no subquery)
114
+ LEFT JOIN tasker_workflow_step_edges dep_edges
115
+ ON dep_edges.to_step_id = ws.workflow_step_id
116
+ LEFT JOIN tasker_workflow_step_transitions parent_states
117
+ ON parent_states.workflow_step_id = dep_edges.from_step_id
118
+ AND parent_states.most_recent = true
119
+
120
+ -- OPTIMIZED: Last failure using index-optimized approach
121
+ LEFT JOIN tasker_workflow_step_transitions last_failure
122
+ ON last_failure.workflow_step_id = ws.workflow_step_id
123
+ AND last_failure.to_state = 'error'
124
+ AND last_failure.most_recent = true
125
+
126
+ -- KEY PERFORMANCE IMPROVEMENT: Filter by task first, then optionally by step IDs
127
+ -- CRITICAL FIX: Include ALL steps for task execution context calculation
128
+ -- Only filter by processed status when specifically querying for ready steps
129
+ WHERE ws.task_id = input_task_id
130
+ AND (step_ids IS NULL OR ws.workflow_step_id = ANY(step_ids))
131
+
132
+ GROUP BY
133
+ ws.workflow_step_id, ws.task_id, ws.named_step_id, ns.name,
134
+ current_state.to_state, last_failure.created_at,
135
+ ws.attempts, ws.retry_limit, ws.backoff_request_seconds, ws.last_attempted_at,
136
+ ws.in_process, ws.processed, ws.retryable, dep_edges.to_step_id,
137
+ current_state.workflow_step_id, last_failure.workflow_step_id;
138
+ END;
139
+ $$;
@@ -0,0 +1,108 @@
1
+ -- System Health Counts Function
2
+ -- Returns comprehensive system health metrics in a single query
3
+ -- No input parameters needed - returns system-wide counts
4
+ -- Output: Single row with all health counts and metrics
5
+
6
+ CREATE OR REPLACE FUNCTION get_system_health_counts_v01()
7
+ RETURNS TABLE (
8
+ -- Task counts
9
+ total_tasks BIGINT,
10
+ pending_tasks BIGINT,
11
+ in_progress_tasks BIGINT,
12
+ complete_tasks BIGINT,
13
+ error_tasks BIGINT,
14
+ cancelled_tasks BIGINT,
15
+
16
+ -- Step counts
17
+ total_steps BIGINT,
18
+ pending_steps BIGINT,
19
+ in_progress_steps BIGINT,
20
+ complete_steps BIGINT,
21
+ error_steps BIGINT,
22
+
23
+ -- Retry-specific counts
24
+ retryable_error_steps BIGINT,
25
+ exhausted_retry_steps BIGINT,
26
+ in_backoff_steps BIGINT,
27
+
28
+ -- Database metrics
29
+ active_connections BIGINT,
30
+ max_connections BIGINT
31
+ ) LANGUAGE plpgsql STABLE AS $$
32
+ BEGIN
33
+ RETURN QUERY
34
+ WITH task_counts AS (
35
+ SELECT
36
+ COUNT(*) as total_tasks,
37
+ COUNT(*) FILTER (WHERE task_state.to_state = 'pending') as pending_tasks,
38
+ COUNT(*) FILTER (WHERE task_state.to_state = 'in_progress') as in_progress_tasks,
39
+ COUNT(*) FILTER (WHERE task_state.to_state = 'complete') as complete_tasks,
40
+ COUNT(*) FILTER (WHERE task_state.to_state = 'error') as error_tasks,
41
+ COUNT(*) FILTER (WHERE task_state.to_state = 'cancelled') as cancelled_tasks
42
+ FROM tasker_tasks t
43
+ LEFT JOIN tasker_task_transitions task_state ON task_state.task_id = t.task_id
44
+ AND task_state.most_recent = true
45
+ ),
46
+ step_counts AS (
47
+ SELECT
48
+ COUNT(*) as total_steps,
49
+ COUNT(*) FILTER (WHERE step_state.to_state = 'pending') as pending_steps,
50
+ COUNT(*) FILTER (WHERE step_state.to_state = 'in_progress') as in_progress_steps,
51
+ COUNT(*) FILTER (WHERE step_state.to_state = 'complete') as complete_steps,
52
+ COUNT(*) FILTER (WHERE step_state.to_state = 'error') as error_steps,
53
+
54
+ -- Retry-specific logic - retryable errors
55
+ COUNT(*) FILTER (
56
+ WHERE step_state.to_state = 'error'
57
+ AND ws.attempts < ws.retry_limit
58
+ AND COALESCE(ws.retryable, true) = true
59
+ ) as retryable_error_steps,
60
+
61
+ -- Exhausted retries
62
+ COUNT(*) FILTER (
63
+ WHERE step_state.to_state = 'error'
64
+ AND ws.attempts >= ws.retry_limit
65
+ ) as exhausted_retry_steps,
66
+
67
+ -- In backoff (error state but not exhausted retries and has last_attempted_at)
68
+ COUNT(*) FILTER (
69
+ WHERE step_state.to_state = 'error'
70
+ AND ws.attempts < ws.retry_limit
71
+ AND COALESCE(ws.retryable, true) = true
72
+ AND ws.last_attempted_at IS NOT NULL
73
+ ) as in_backoff_steps
74
+
75
+ FROM tasker_workflow_steps ws
76
+ LEFT JOIN tasker_workflow_step_transitions step_state ON step_state.workflow_step_id = ws.workflow_step_id
77
+ AND step_state.most_recent = true
78
+ ),
79
+ connection_info AS (
80
+ SELECT
81
+ COUNT(*) as active_connections,
82
+ COALESCE((SELECT setting::BIGINT FROM pg_settings WHERE name = 'max_connections'), 0) as max_connections
83
+ FROM pg_stat_activity
84
+ WHERE datname = current_database()
85
+ AND state = 'active'
86
+ )
87
+ SELECT
88
+ tc.total_tasks,
89
+ tc.pending_tasks,
90
+ tc.in_progress_tasks,
91
+ tc.complete_tasks,
92
+ tc.error_tasks,
93
+ tc.cancelled_tasks,
94
+ sc.total_steps,
95
+ sc.pending_steps,
96
+ sc.in_progress_steps,
97
+ sc.complete_steps,
98
+ sc.error_steps,
99
+ sc.retryable_error_steps,
100
+ sc.exhausted_retry_steps,
101
+ sc.in_backoff_steps,
102
+ ci.active_connections,
103
+ ci.max_connections
104
+ FROM task_counts tc
105
+ CROSS JOIN step_counts sc
106
+ CROSS JOIN connection_info ci;
107
+ END;
108
+ $$;
@@ -0,0 +1,108 @@
1
+ -- Task Execution Context Function
2
+ -- Uses the step readiness function to build aggregated task context
3
+ -- Input: Single task_id
4
+ -- Output: Single row with task execution context
5
+
6
+ CREATE OR REPLACE FUNCTION get_task_execution_context(input_task_id BIGINT)
7
+ RETURNS TABLE(
8
+ task_id BIGINT,
9
+ named_task_id INTEGER,
10
+ status TEXT,
11
+ total_steps BIGINT,
12
+ pending_steps BIGINT,
13
+ in_progress_steps BIGINT,
14
+ completed_steps BIGINT,
15
+ failed_steps BIGINT,
16
+ ready_steps BIGINT,
17
+ execution_status TEXT,
18
+ recommended_action TEXT,
19
+ completion_percentage DECIMAL,
20
+ health_status TEXT
21
+ ) LANGUAGE plpgsql STABLE AS $$
22
+ BEGIN
23
+ -- Use the step readiness function to get step data, then aggregate
24
+ -- The step readiness function handles the case where no steps exist
25
+ RETURN QUERY
26
+ WITH step_data AS (
27
+ SELECT * FROM get_step_readiness_status(input_task_id, NULL)
28
+ ),
29
+ task_info AS (
30
+ SELECT
31
+ t.task_id,
32
+ t.named_task_id,
33
+ COALESCE(task_state.to_state, 'pending')::TEXT as current_status
34
+ FROM tasker_tasks t
35
+ LEFT JOIN tasker_task_transitions task_state
36
+ ON task_state.task_id = t.task_id
37
+ AND task_state.most_recent = true
38
+ WHERE t.task_id = input_task_id
39
+ ),
40
+ aggregated_stats AS (
41
+ SELECT
42
+ COUNT(*) as total_steps,
43
+ COUNT(CASE WHEN sd.current_state = 'pending' THEN 1 END) as pending_steps,
44
+ COUNT(CASE WHEN sd.current_state = 'in_progress' THEN 1 END) as in_progress_steps,
45
+ COUNT(CASE WHEN sd.current_state IN ('complete', 'resolved_manually') THEN 1 END) as completed_steps,
46
+ COUNT(CASE WHEN sd.current_state = 'error' THEN 1 END) as failed_steps,
47
+ COUNT(CASE WHEN sd.ready_for_execution = true THEN 1 END) as ready_steps,
48
+ -- Count PERMANENTLY blocked failures (exhausted retries OR explicitly marked as not retryable)
49
+ COUNT(CASE WHEN sd.current_state = 'error'
50
+ AND (sd.attempts >= sd.retry_limit) THEN 1 END) as permanently_blocked_steps
51
+ FROM step_data sd
52
+ )
53
+ SELECT
54
+ ti.task_id,
55
+ ti.named_task_id,
56
+ ti.current_status as status,
57
+
58
+ -- Step Statistics
59
+ COALESCE(ast.total_steps, 0) as total_steps,
60
+ COALESCE(ast.pending_steps, 0) as pending_steps,
61
+ COALESCE(ast.in_progress_steps, 0) as in_progress_steps,
62
+ COALESCE(ast.completed_steps, 0) as completed_steps,
63
+ COALESCE(ast.failed_steps, 0) as failed_steps,
64
+ COALESCE(ast.ready_steps, 0) as ready_steps,
65
+
66
+ -- FIXED: Execution State Logic
67
+ CASE
68
+ WHEN COALESCE(ast.ready_steps, 0) > 0 THEN 'has_ready_steps'
69
+ WHEN COALESCE(ast.in_progress_steps, 0) > 0 THEN 'processing'
70
+ -- OLD BUG: WHEN COALESCE(ast.failed_steps, 0) > 0 AND COALESCE(ast.ready_steps, 0) = 0 THEN 'blocked_by_failures'
71
+ -- NEW FIX: Only blocked if failed steps are NOT retry-eligible
72
+ WHEN COALESCE(ast.permanently_blocked_steps, 0) > 0 AND COALESCE(ast.ready_steps, 0) = 0 THEN 'blocked_by_failures'
73
+ WHEN COALESCE(ast.completed_steps, 0) = COALESCE(ast.total_steps, 0) AND COALESCE(ast.total_steps, 0) > 0 THEN 'all_complete'
74
+ ELSE 'waiting_for_dependencies'
75
+ END as execution_status,
76
+
77
+ -- FIXED: Recommended Action Logic
78
+ CASE
79
+ WHEN COALESCE(ast.ready_steps, 0) > 0 THEN 'execute_ready_steps'
80
+ WHEN COALESCE(ast.in_progress_steps, 0) > 0 THEN 'wait_for_completion'
81
+ -- OLD BUG: WHEN COALESCE(ast.failed_steps, 0) > 0 AND COALESCE(ast.ready_steps, 0) = 0 THEN 'handle_failures'
82
+ -- NEW FIX: Only handle failures if they're truly blocked
83
+ WHEN COALESCE(ast.permanently_blocked_steps, 0) > 0 AND COALESCE(ast.ready_steps, 0) = 0 THEN 'handle_failures'
84
+ WHEN COALESCE(ast.completed_steps, 0) = COALESCE(ast.total_steps, 0) AND COALESCE(ast.total_steps, 0) > 0 THEN 'finalize_task'
85
+ ELSE 'wait_for_dependencies'
86
+ END as recommended_action,
87
+
88
+ -- Progress Metrics
89
+ CASE
90
+ WHEN COALESCE(ast.total_steps, 0) = 0 THEN 0.0
91
+ ELSE ROUND((COALESCE(ast.completed_steps, 0)::decimal / COALESCE(ast.total_steps, 1)::decimal) * 100, 2)
92
+ END as completion_percentage,
93
+
94
+ -- FIXED: Health Status Logic
95
+ CASE
96
+ WHEN COALESCE(ast.failed_steps, 0) = 0 THEN 'healthy'
97
+ WHEN COALESCE(ast.failed_steps, 0) > 0 AND COALESCE(ast.ready_steps, 0) > 0 THEN 'recovering'
98
+ -- NEW FIX: Only blocked if failures are truly not retry-eligible
99
+ WHEN COALESCE(ast.permanently_blocked_steps, 0) > 0 AND COALESCE(ast.ready_steps, 0) = 0 THEN 'blocked'
100
+ -- NEW: Waiting state for retry-eligible failures with backoff
101
+ WHEN COALESCE(ast.failed_steps, 0) > 0 AND COALESCE(ast.permanently_blocked_steps, 0) = 0 AND COALESCE(ast.ready_steps, 0) = 0 THEN 'recovering'
102
+ ELSE 'unknown'
103
+ END as health_status
104
+
105
+ FROM task_info ti
106
+ CROSS JOIN aggregated_stats ast;
107
+ END;
108
+ $$;