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,716 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative '../events/event_payload_builder'
4
+ require_relative '../events/custom_registry'
5
+ require_relative 'structured_logging'
6
+
7
+ module Tasker
8
+ module Concerns
9
+ # EventPublisher provides a clean interface for publishing events
10
+ #
11
+ # This concern provides domain-specific event publishing methods that automatically
12
+ # build standardized payloads and resolve event constants. The API is designed for
13
+ # maximum clarity and minimum cognitive overhead.
14
+ #
15
+ # Enhanced with structured logging integration for production observability.
16
+ #
17
+ # Usage:
18
+ # include Tasker::Concerns::EventPublisher
19
+ #
20
+ # # Step events - method name determines event type automatically
21
+ # publish_step_completed(step, operation_count: 42)
22
+ # publish_step_failed(step, error: exception)
23
+ # publish_step_started(step)
24
+ #
25
+ # # Task events - clean and obvious
26
+ # publish_task_started(task)
27
+ # publish_task_completed(task, total_duration: 120.5)
28
+ # publish_task_failed(task, error_message: "Payment failed")
29
+ module EventPublisher
30
+ extend ActiveSupport::Concern
31
+
32
+ included do
33
+ # Include structured logging for event publishing observability
34
+ include Tasker::Concerns::StructuredLogging
35
+ end
36
+
37
+ # ========================================================================
38
+ # CLEAN STEP EVENT PUBLISHING - METHOD NAME = EVENT TYPE
39
+ # ========================================================================
40
+
41
+ # Publish step started event
42
+ # Automatically resolves to StepEvents::EXECUTION_REQUESTED with :started event type
43
+ #
44
+ # @param step [WorkflowStep] The step being started
45
+ # @param context [Hash] Additional context to merge into payload
46
+ # @return [void]
47
+ def publish_step_started(step, **context)
48
+ payload = build_step_payload(step, :started, context)
49
+ publish_event_with_logging(Tasker::Constants::StepEvents::EXECUTION_REQUESTED, payload) do
50
+ log_step_event(step, :started, **context.slice(:processing_mode, :concurrent_batch_size))
51
+ end
52
+ end
53
+
54
+ # Publish step before handle event
55
+ # Automatically resolves to StepEvents::BEFORE_HANDLE with :before_handle event type
56
+ #
57
+ # @param step [WorkflowStep] The step about to be handled
58
+ # @param context [Hash] Additional context to merge into payload
59
+ # @return [void]
60
+ def publish_step_before_handle(step, **context)
61
+ payload = build_step_payload(step, :before_handle, context)
62
+ publish_event_with_logging(Tasker::Constants::StepEvents::BEFORE_HANDLE, payload) do
63
+ log_step_event(step, :before_handle, **context.slice(:handler_class, :dependencies_met))
64
+ end
65
+ end
66
+
67
+ # Publish step completed event
68
+ # Automatically resolves to StepEvents::COMPLETED with :completed event type
69
+ #
70
+ # @param step [WorkflowStep] The step that completed
71
+ # @param context [Hash] Additional context to merge into payload
72
+ # @return [void]
73
+ def publish_step_completed(step, **context)
74
+ payload = build_step_payload(step, :completed, context)
75
+ publish_event_with_logging(Tasker::Constants::StepEvents::COMPLETED, payload) do
76
+ duration = context[:duration] || extract_duration_from_step(step)
77
+ log_step_event(step, :completed, duration: duration, **context.slice(:operation_count, :records_processed))
78
+ end
79
+ end
80
+
81
+ # Publish step failed event
82
+ # Automatically resolves to StepEvents::FAILED with :failed event type
83
+ # Automatically extracts error information if :error is provided
84
+ #
85
+ # @param step [WorkflowStep] The step that failed
86
+ # @param error [Exception, nil] The exception that caused the failure
87
+ # @param context [Hash] Additional context to merge into payload
88
+ # @return [void]
89
+ def publish_step_failed(step, error: nil, **context)
90
+ # Automatically extract error information into context
91
+ if error
92
+ context = context.merge(
93
+ error_message: error.message,
94
+ error_class: error.class.name,
95
+ backtrace: error.backtrace&.first(10)
96
+ )
97
+ end
98
+
99
+ payload = build_step_payload(step, :failed, context)
100
+ publish_event_with_logging(Tasker::Constants::StepEvents::FAILED, payload) do
101
+ duration = context[:duration] || extract_duration_from_step(step)
102
+ log_step_event(step, :failed, duration: duration, error: error&.message)
103
+ log_exception(error, context: { step_id: step.workflow_step_id, task_id: step.task.task_id }) if error
104
+ end
105
+ end
106
+
107
+ # Publish step retry requested event
108
+ # Automatically resolves to StepEvents::RETRY_REQUESTED with :retry event type
109
+ #
110
+ # @param step [WorkflowStep] The step being retried
111
+ # @param retry_reason [String] The reason for the retry
112
+ # @param context [Hash] Additional context to merge into payload
113
+ # @return [void]
114
+ def publish_step_retry_requested(step, retry_reason: 'Step execution failed', **context)
115
+ context = context.merge(retry_reason: retry_reason)
116
+ payload = build_step_payload(step, :retry, context)
117
+ publish_event_with_logging(Tasker::Constants::StepEvents::RETRY_REQUESTED, payload) do
118
+ log_step_event(step, :retry_requested,
119
+ retry_reason: retry_reason,
120
+ attempt_count: step.attempts,
121
+ **context.slice(:backoff_seconds, :max_retries))
122
+ end
123
+ end
124
+
125
+ # Publish step cancelled event
126
+ # Automatically resolves to StepEvents::CANCELLED with :cancelled event type
127
+ #
128
+ # @param step [WorkflowStep] The step being cancelled
129
+ # @param cancellation_reason [String] The reason for cancellation
130
+ # @param context [Hash] Additional context to merge into payload
131
+ # @return [void]
132
+ def publish_step_cancelled(step, cancellation_reason: 'Step cancelled', **context)
133
+ context = context.merge(cancellation_reason: cancellation_reason)
134
+ payload = build_step_payload(step, :cancelled, context)
135
+ publish_event_with_logging(Tasker::Constants::StepEvents::CANCELLED, payload) do
136
+ log_step_event(step, :cancelled, cancellation_reason: cancellation_reason)
137
+ end
138
+ end
139
+
140
+ # ========================================================================
141
+ # CLEAN TASK EVENT PUBLISHING - METHOD NAME = EVENT TYPE
142
+ # ========================================================================
143
+
144
+ # Publish task started event
145
+ # Automatically resolves to TaskEvents::START_REQUESTED with :started event type
146
+ #
147
+ # @param task [Task] The task being started
148
+ # @param context [Hash] Additional context to merge into payload
149
+ # @return [void]
150
+ def publish_task_started(task, **context)
151
+ payload = build_task_payload(task, :started, context)
152
+ publish_event_with_logging(Tasker::Constants::TaskEvents::START_REQUESTED, payload) do
153
+ log_task_event(task, :started, **context.slice(:execution_mode, :priority, :step_count))
154
+ end
155
+ end
156
+
157
+ # Publish task completed event
158
+ # Automatically resolves to TaskEvents::COMPLETED with :completed event type
159
+ #
160
+ # @param task [Task] The task that completed
161
+ # @param context [Hash] Additional context to merge into payload
162
+ # @return [void]
163
+ def publish_task_completed(task, **context)
164
+ payload = build_task_payload(task, :completed, context)
165
+ publish_event_with_logging(Tasker::Constants::TaskEvents::COMPLETED, payload) do
166
+ log_task_event(task, :completed, **context.slice(:total_duration, :completed_steps, :total_steps))
167
+ end
168
+ end
169
+
170
+ # Publish task failed event
171
+ # Automatically resolves to TaskEvents::FAILED with :failed event type
172
+ #
173
+ # @param task [Task] The task that failed
174
+ # @param error_message [String] The error message
175
+ # @param error_steps [Array] Array of failed step information
176
+ # @param context [Hash] Additional context to merge into payload
177
+ # @return [void]
178
+ def publish_task_failed(task, error_message: 'Task execution failed', error_steps: [], **context)
179
+ context = context.merge(
180
+ error_message: error_message,
181
+ error_steps: error_steps
182
+ )
183
+
184
+ payload = build_task_payload(task, :failed, context)
185
+ publish_event_with_logging(Tasker::Constants::TaskEvents::FAILED, payload) do
186
+ log_task_event(task, :failed,
187
+ error: error_message,
188
+ failed_step_count: error_steps.size,
189
+ **context.slice(:total_duration, :completed_steps))
190
+ end
191
+ end
192
+
193
+ # Publish task retry requested event
194
+ # Automatically resolves to TaskEvents::RETRY_REQUESTED with :retry event type
195
+ #
196
+ # @param task [Task] The task being retried
197
+ # @param retry_reason [String] The reason for the retry
198
+ # @param context [Hash] Additional context to merge into payload
199
+ # @return [void]
200
+ def publish_task_retry_requested(task, retry_reason: 'Task retry requested', **context)
201
+ context = context.merge(retry_reason: retry_reason)
202
+ payload = build_task_payload(task, :retry, context)
203
+ publish_event_with_logging(Tasker::Constants::TaskEvents::RETRY_REQUESTED, payload) do
204
+ log_task_event(task, :retry_requested, retry_reason: retry_reason)
205
+ end
206
+ end
207
+
208
+ # ========================================================================
209
+ # CLEAN WORKFLOW ORCHESTRATION EVENTS - SIMPLIFIED API
210
+ # ========================================================================
211
+
212
+ # Publish workflow task started event (orchestration layer)
213
+ # Automatically resolves to WorkflowEvents::TASK_STARTED
214
+ #
215
+ # @param task_id [String] The task ID
216
+ # @param context [Hash] Additional orchestration context
217
+ # @return [void]
218
+ def publish_workflow_task_started(task_id, **context)
219
+ context = context.merge(task_id: task_id)
220
+ payload = build_orchestration_payload(:task_started, context)
221
+ publish_event_with_logging(Tasker::Constants::WorkflowEvents::TASK_STARTED, payload) do
222
+ log_orchestration_event('workflow_task_started', :started, task_id: task_id, **context)
223
+ end
224
+ end
225
+
226
+ # Publish workflow step completed event (orchestration layer)
227
+ # Automatically resolves to WorkflowEvents::STEP_COMPLETED
228
+ #
229
+ # @param task_id [String] The task ID
230
+ # @param step_id [String] The step ID
231
+ # @param context [Hash] Additional orchestration context
232
+ # @return [void]
233
+ def publish_workflow_step_completed(task_id, step_id, **context)
234
+ context = context.merge(task_id: task_id, step_id: step_id)
235
+ payload = build_orchestration_payload(:step_completed, context)
236
+ publish_event_with_logging(Tasker::Constants::WorkflowEvents::STEP_COMPLETED, payload) do
237
+ log_orchestration_event('workflow_step_completed', :completed,
238
+ task_id: task_id, step_id: step_id, **context)
239
+ end
240
+ end
241
+
242
+ # Publish viable steps discovered event
243
+ # Automatically resolves to WorkflowEvents::VIABLE_STEPS_DISCOVERED
244
+ #
245
+ # @param task_id [String] The task ID
246
+ # @param step_ids [Array<String>] Array of step IDs that are viable
247
+ # @param processing_mode [String] The processing mode ('concurrent' or 'sequential')
248
+ # @param context [Hash] Additional orchestration context
249
+ # @return [void]
250
+ def publish_viable_steps_discovered(task_id, step_ids, processing_mode: 'concurrent', **context)
251
+ context = context.merge(
252
+ task_id: task_id,
253
+ step_ids: step_ids,
254
+ processing_mode: processing_mode,
255
+ step_count: step_ids.size
256
+ )
257
+
258
+ payload = build_orchestration_payload(:viable_steps_discovered, context)
259
+ publish_event_with_logging(Tasker::Constants::WorkflowEvents::VIABLE_STEPS_DISCOVERED, payload) do
260
+ log_orchestration_event('viable_steps_discovered', :discovered,
261
+ task_id: task_id, step_count: step_ids.size, processing_mode: processing_mode)
262
+ end
263
+ end
264
+
265
+ # Publish no viable steps event
266
+ # Automatically resolves to WorkflowEvents::NO_VIABLE_STEPS
267
+ #
268
+ # @param task_id [String] The task ID
269
+ # @param reason [String] The reason why no steps are viable
270
+ # @param context [Hash] Additional orchestration context
271
+ # @return [void]
272
+ def publish_no_viable_steps(task_id, reason: 'No steps ready for execution', **context)
273
+ context = context.merge(task_id: task_id, reason: reason)
274
+ payload = build_orchestration_payload(:no_viable_steps, context)
275
+ publish_event_with_logging(Tasker::Constants::WorkflowEvents::NO_VIABLE_STEPS, payload) do
276
+ log_orchestration_event('no_viable_steps', :detected, task_id: task_id, reason: reason)
277
+ end
278
+ end
279
+
280
+ # ========================================================================
281
+ # TASK FINALIZATION EVENTS WITH STRUCTURED LOGGING
282
+ # ========================================================================
283
+
284
+ # Publish task finalization started event
285
+ #
286
+ # @param task [Task] The task being finalized
287
+ # @param processed_steps_count [Integer] Number of steps processed
288
+ # @param context [Hash] Additional context
289
+ # @return [void]
290
+ def publish_task_finalization_started(task, processed_steps_count: 0, **context)
291
+ context = context.merge(
292
+ task_id: task.task_id,
293
+ processed_steps_count: processed_steps_count
294
+ )
295
+
296
+ payload = build_orchestration_payload(:task_finalization_started, context)
297
+ publish_event_with_logging(Tasker::Constants::WorkflowEvents::TASK_FINALIZATION_STARTED, payload) do
298
+ log_orchestration_event('task_finalization', :started,
299
+ task_id: task.task_id, processed_steps_count: processed_steps_count)
300
+ end
301
+ end
302
+
303
+ # Publish task finalization completed event
304
+ #
305
+ # @param task [Task] The task that was finalized
306
+ # @param processed_steps_count [Integer] Number of steps processed
307
+ # @param context [Hash] Additional context
308
+ # @return [void]
309
+ def publish_task_finalization_completed(task, processed_steps_count: 0, **context)
310
+ context = context.merge(
311
+ task_id: task.task_id,
312
+ processed_steps_count: processed_steps_count,
313
+ final_status: task.status
314
+ )
315
+
316
+ payload = build_orchestration_payload(:task_finalization_completed, context)
317
+ publish_event_with_logging(Tasker::Constants::WorkflowEvents::TASK_FINALIZATION_COMPLETED, payload) do
318
+ log_orchestration_event('task_finalization', :completed,
319
+ task_id: task.task_id,
320
+ final_status: task.status,
321
+ processed_steps_count: processed_steps_count)
322
+ end
323
+ end
324
+
325
+ # Publish task pending transition event (for synchronous processing)
326
+ # Automatically resolves to TaskEvents::INITIALIZE_REQUESTED with pending context
327
+ #
328
+ # @param task [Task] The task being set to pending
329
+ # @param reason [String] The reason for setting to pending
330
+ # @param context [Hash] Additional pending context
331
+ # @return [void]
332
+ def publish_task_pending_transition(task, reason: 'Task set to pending', **context)
333
+ context = context.merge(
334
+ task_id: task.task_id,
335
+ task_name: task.name,
336
+ reason: reason
337
+ )
338
+
339
+ payload = build_task_payload(task, :pending_transition, context)
340
+ publish_event(Tasker::Constants::TaskEvents::INITIALIZE_REQUESTED, payload)
341
+ end
342
+
343
+ # Publish workflow unclear state event (for monitoring/alerting)
344
+ # Automatically resolves to WorkflowEvents::TASK_STATE_UNCLEAR
345
+ #
346
+ # @param task [Task] The task in unclear state
347
+ # @param reason [String] The reason the state is unclear
348
+ # @param context [Hash] Additional unclear state context
349
+ # @return [void]
350
+ def publish_workflow_state_unclear(task, reason: 'Task in unclear state', **context)
351
+ context = context.merge(
352
+ task_id: task.task_id,
353
+ task_name: task.name,
354
+ reason: reason
355
+ )
356
+
357
+ payload = build_orchestration_payload(:task_state_unclear, context)
358
+ publish_event(Tasker::Constants::WorkflowEvents::TASK_STATE_UNCLEAR, payload)
359
+ end
360
+
361
+ # ========================================================================
362
+ # TASK REENQUEUE ORCHESTRATION EVENTS - NEW CLEAN HELPERS
363
+ # ========================================================================
364
+
365
+ # Publish task reenqueue started event
366
+ # Automatically resolves to WorkflowEvents::TASK_REENQUEUE_STARTED
367
+ #
368
+ # @param task [Task] The task being reenqueued
369
+ # @param reason [String] The reason for reenqueue
370
+ # @param context [Hash] Additional reenqueue context
371
+ # @return [void]
372
+ def publish_task_reenqueue_started(task, reason: 'Task reenqueue started', **context)
373
+ context = context.merge(
374
+ task_id: task.task_id,
375
+ task_name: task.name,
376
+ reason: reason,
377
+ current_status: task.status,
378
+ timestamp: Time.current
379
+ )
380
+
381
+ payload = build_orchestration_payload(:task_reenqueue_started, context)
382
+ publish_event(Tasker::Constants::WorkflowEvents::TASK_REENQUEUE_STARTED, payload)
383
+ end
384
+
385
+ # Publish task reenqueue requested event
386
+ # Automatically resolves to WorkflowEvents::TASK_REENQUEUE_REQUESTED
387
+ #
388
+ # @param task [Task] The task reenqueue was requested for
389
+ # @param reason [String] The reason for reenqueue
390
+ # @param context [Hash] Additional reenqueue context
391
+ # @return [void]
392
+ def publish_task_reenqueue_requested(task, reason: 'Task reenqueue requested', **context)
393
+ context = context.merge(
394
+ task_id: task.task_id,
395
+ task_name: task.name,
396
+ reason: reason,
397
+ timestamp: Time.current
398
+ )
399
+
400
+ payload = build_orchestration_payload(:task_reenqueue_requested, context)
401
+ publish_event(Tasker::Constants::WorkflowEvents::TASK_REENQUEUE_REQUESTED, payload)
402
+ end
403
+
404
+ # Publish task reenqueue failed event
405
+ # Automatically resolves to WorkflowEvents::TASK_REENQUEUE_FAILED
406
+ #
407
+ # @param task [Task] The task that failed to reenqueue
408
+ # @param reason [String] The reason for reenqueue attempt
409
+ # @param error [String] The error message
410
+ # @param context [Hash] Additional reenqueue context
411
+ # @return [void]
412
+ def publish_task_reenqueue_failed(task, reason: 'Task reenqueue failed', error: 'Unknown error', **context)
413
+ context = context.merge(
414
+ task_id: task.task_id,
415
+ task_name: task.name,
416
+ reason: reason,
417
+ error: error,
418
+ timestamp: Time.current
419
+ )
420
+
421
+ payload = build_orchestration_payload(:task_reenqueue_failed, context)
422
+ publish_event(Tasker::Constants::WorkflowEvents::TASK_REENQUEUE_FAILED, payload)
423
+ end
424
+
425
+ # Publish task reenqueue delayed event
426
+ # Automatically resolves to WorkflowEvents::TASK_REENQUEUE_DELAYED
427
+ #
428
+ # @param task [Task] The task being delayed for reenqueue
429
+ # @param delay_seconds [Integer] Number of seconds to delay
430
+ # @param reason [String] The reason for delayed reenqueue
431
+ # @param context [Hash] Additional reenqueue context
432
+ # @return [void]
433
+ def publish_task_reenqueue_delayed(task, delay_seconds:, reason: 'Task reenqueue delayed', **context)
434
+ context = context.merge(
435
+ task_id: task.task_id,
436
+ task_name: task.name,
437
+ reason: reason,
438
+ delay_seconds: delay_seconds,
439
+ scheduled_for: Time.current + delay_seconds.seconds,
440
+ timestamp: Time.current
441
+ )
442
+
443
+ payload = build_orchestration_payload(:task_reenqueue_delayed, context)
444
+ publish_event(Tasker::Constants::WorkflowEvents::TASK_REENQUEUE_DELAYED, payload)
445
+ end
446
+
447
+ # ========================================================================
448
+ # STEPS EXECUTION ORCHESTRATION EVENTS - NEW CLEAN HELPERS
449
+ # ========================================================================
450
+
451
+ # Publish steps execution started event (batch processing)
452
+ # Automatically resolves to WorkflowEvents::STEPS_EXECUTION_STARTED
453
+ #
454
+ # @param task [Task] The task whose steps are being executed
455
+ # @param step_count [Integer] Number of steps being executed
456
+ # @param processing_mode [String] The processing mode (concurrent/sequential)
457
+ # @param context [Hash] Additional execution context
458
+ # @return [void]
459
+ def publish_steps_execution_started(task, step_count:, processing_mode: 'concurrent', **context)
460
+ context = context.merge(
461
+ task_id: task.task_id,
462
+ task_name: task.name,
463
+ step_count: step_count,
464
+ processing_mode: processing_mode
465
+ )
466
+
467
+ payload = build_orchestration_payload(:steps_execution_started, context)
468
+ publish_event(Tasker::Constants::WorkflowEvents::STEPS_EXECUTION_STARTED, payload)
469
+ end
470
+
471
+ # Publish steps execution completed event (batch processing)
472
+ # Automatically resolves to WorkflowEvents::STEPS_EXECUTION_COMPLETED
473
+ #
474
+ # @param task [Task] The task whose steps were executed
475
+ # @param processed_count [Integer] Number of steps processed
476
+ # @param successful_count [Integer] Number of steps that succeeded
477
+ # @param context [Hash] Additional execution context
478
+ # @return [void]
479
+ def publish_steps_execution_completed(task, processed_count:, successful_count:, **context)
480
+ context = context.merge(
481
+ task_id: task.task_id,
482
+ task_name: task.name,
483
+ processed_count: processed_count,
484
+ successful_count: successful_count
485
+ )
486
+
487
+ payload = build_orchestration_payload(:steps_execution_completed, context)
488
+ publish_event_with_logging(Tasker::Constants::WorkflowEvents::STEPS_EXECUTION_COMPLETED, payload) do
489
+ log_orchestration_event('steps_execution_completed', :completed,
490
+ task_id: task.task_id,
491
+ processed_count: processed_count,
492
+ successful_count: successful_count,
493
+ failure_count: processed_count - successful_count)
494
+ end
495
+ end
496
+
497
+ # ========================================================================
498
+ # STEP OBSERVABILITY EVENTS - NEW CLEAN HELPERS
499
+ # ========================================================================
500
+
501
+ # Publish step backoff event (for retry/rate limiting scenarios)
502
+ # Automatically resolves to ObservabilityEvents::Step::BACKOFF
503
+ #
504
+ # @param step [WorkflowStep] The step being backed off
505
+ # @param backoff_seconds [Float] Number of seconds to wait
506
+ # @param backoff_type [String] Type of backoff (server_requested/exponential)
507
+ # @param context [Hash] Additional backoff context
508
+ # @return [void]
509
+ def publish_step_backoff(step, backoff_seconds:, backoff_type: 'exponential', **context)
510
+ context = context.merge(
511
+ step_id: step.workflow_step_id,
512
+ step_name: step.name,
513
+ backoff_seconds: backoff_seconds,
514
+ backoff_type: backoff_type
515
+ )
516
+
517
+ payload = build_step_payload(step, :backoff, context)
518
+ publish_event_with_logging(Tasker::Constants::ObservabilityEvents::Step::BACKOFF, payload) do
519
+ log_step_event(step, :backoff,
520
+ backoff_seconds: backoff_seconds,
521
+ backoff_type: backoff_type,
522
+ **context.slice(:retry_attempt, :max_retries))
523
+ end
524
+ end
525
+
526
+ # ========================================================================
527
+ # TASK OBSERVABILITY EVENTS - NEW CLEAN HELPERS
528
+ # ========================================================================
529
+
530
+ # Publish task enqueue event (for job scheduling observability)
531
+ # Automatically resolves to ObservabilityEvents::Task::ENQUEUE
532
+ #
533
+ # @param task [Task] The task being enqueued
534
+ # @param context [Hash] Additional enqueue context
535
+ # @return [void]
536
+ def publish_task_enqueue(task, **context)
537
+ context = context.merge(
538
+ task_id: task.task_id,
539
+ task_name: task.name,
540
+ task_context: task.context
541
+ )
542
+
543
+ payload = build_task_payload(task, :enqueue, context)
544
+ publish_event_with_logging(Tasker::Constants::ObservabilityEvents::Task::ENQUEUE, payload) do
545
+ log_task_event(task, :enqueued, **context.slice(:queue_name, :job_class, :priority))
546
+ end
547
+ end
548
+
549
+ # ========================================================================
550
+ # CUSTOM EVENT PUBLISHING - DEVELOPER-FACING API
551
+ # ========================================================================
552
+
553
+ # Publish a custom event with standard metadata
554
+ # Assumes the event is already registered
555
+ #
556
+ # @param event_name [String] Event name
557
+ # @param payload [Hash] Event payload
558
+ # @return [void]
559
+ def publish_custom_event(event_name, payload = {})
560
+ # Add standard metadata
561
+ enhanced_payload = payload.merge(
562
+ event_type: 'custom',
563
+ timestamp: Time.current
564
+ )
565
+
566
+ publish_event_with_logging(event_name, enhanced_payload) do
567
+ log_structured(:info, 'Custom event published',
568
+ event_name: event_name,
569
+ event_type: 'custom',
570
+ **payload.slice(:task_id, :step_id, :operation, :context))
571
+ end
572
+ end
573
+
574
+ # ========================================================================
575
+ # CONTEXT-AWARE EVENT PUBLISHING (Advanced - for special cases)
576
+ # ========================================================================
577
+
578
+ # Automatically determine and publish the appropriate step event based on step state
579
+ # This method uses the step's current state to infer the most appropriate event type
580
+ #
581
+ # @param step [WorkflowStep] The step object
582
+ # @param context_hint [Symbol, nil] Optional hint about the context
583
+ # @param context [Hash] Additional context to merge into payload
584
+ # @return [void]
585
+ def publish_step_event_for_context(step, context_hint: nil, **context)
586
+ event_type = context_hint || infer_step_event_type_from_state(step)
587
+
588
+ case event_type
589
+ when :started, :execution_requested
590
+ publish_step_started(step, **context)
591
+ when :completed, :success
592
+ publish_step_completed(step, **context)
593
+ when :failed, :failure, :error
594
+ publish_step_failed(step, **context)
595
+ when :retry, :retry_requested
596
+ publish_step_retry_requested(step, **context)
597
+ when :cancelled
598
+ publish_step_cancelled(step, **context)
599
+ else
600
+ Rails.logger.warn("Unknown step event context: #{event_type} for step #{step.workflow_step_id}")
601
+ end
602
+ end
603
+
604
+ # Infer step event type from step state and context
605
+ #
606
+ # @param step [WorkflowStep] The step object
607
+ # @return [Symbol] The inferred event type
608
+ def infer_step_event_type_from_state(step)
609
+ case step.status
610
+ when Tasker::Constants::WorkflowStepStatuses::IN_PROGRESS
611
+ :started
612
+ when Tasker::Constants::WorkflowStepStatuses::COMPLETE
613
+ :completed
614
+ when Tasker::Constants::WorkflowStepStatuses::ERROR
615
+ :failed
616
+ when Tasker::Constants::WorkflowStepStatuses::CANCELLED
617
+ :cancelled
618
+ else
619
+ :started # Default fallback
620
+ end
621
+ end
622
+
623
+ private
624
+
625
+ # Core publish method with structured logging integration
626
+ #
627
+ # @param event_constant [String] The event constant
628
+ # @param payload [Hash] The event payload
629
+ # @param block [Proc] Optional block for structured logging
630
+ # @return [void]
631
+ def publish_event_with_logging(event_constant, payload = {})
632
+ # Add timestamp if not present
633
+ payload[:timestamp] ||= Time.current
634
+
635
+ # Execute structured logging if block provided
636
+ if block_given?
637
+ begin
638
+ yield
639
+ rescue StandardError => e
640
+ Rails.logger.debug { "EventPublisher: Structured logging failed for #{event_constant}: #{e.message}" }
641
+ end
642
+ end
643
+
644
+ # Publish through the unified publisher
645
+ Tasker::Events::Publisher.instance.publish(event_constant, payload)
646
+ rescue StandardError => e
647
+ # Trap publishing errors so they don't break core system flow
648
+ Rails.logger.error { "Error publishing event #{event_constant}: #{e.message}" }
649
+ end
650
+
651
+ # Core publish method - used internally by domain-specific methods
652
+ #
653
+ # @param event_constant [String] The event constant
654
+ # @param payload [Hash] The event payload
655
+ # @return [void]
656
+ def publish_event(event_constant, payload = {})
657
+ publish_event_with_logging(event_constant, payload)
658
+ end
659
+
660
+ # Extract duration from step timing information
661
+ #
662
+ # @param step [WorkflowStep] The step to extract duration from
663
+ # @return [Float, nil] Duration in seconds or nil if not available
664
+ def extract_duration_from_step(step)
665
+ return nil unless step.updated_at && step.created_at
666
+
667
+ # Simple duration calculation - can be enhanced with more precise timing
668
+ (step.updated_at - step.created_at).to_f
669
+ end
670
+
671
+ # Build standardized step payload automatically
672
+ # Method name determines event type, no redundant parameters needed
673
+ #
674
+ # @param step [WorkflowStep] The step object
675
+ # @param event_type [Symbol] The event type (inferred from calling method)
676
+ # @param context [Hash] Additional context to merge
677
+ # @return [Hash] Standardized event payload
678
+ def build_step_payload(step, event_type, context = {})
679
+ Tasker::Events::EventPayloadBuilder.build_step_payload(
680
+ step,
681
+ step.task,
682
+ event_type: event_type,
683
+ additional_context: context
684
+ )
685
+ end
686
+
687
+ # Build standardized task payload automatically
688
+ # Method name determines event type, no redundant parameters needed
689
+ #
690
+ # @param task [Task] The task object
691
+ # @param event_type [Symbol] The event type (inferred from calling method)
692
+ # @param context [Hash] Additional context to merge
693
+ # @return [Hash] Standardized event payload
694
+ def build_task_payload(task, event_type, context = {})
695
+ Tasker::Events::EventPayloadBuilder.build_task_payload(
696
+ task,
697
+ event_type: event_type,
698
+ additional_context: context
699
+ )
700
+ end
701
+
702
+ # Build standardized orchestration payload automatically
703
+ # Method name determines event type, no redundant parameters needed
704
+ #
705
+ # @param event_type [Symbol] The orchestration event type
706
+ # @param context [Hash] The orchestration context
707
+ # @return [Hash] Standardized orchestration payload
708
+ def build_orchestration_payload(event_type, context = {})
709
+ Tasker::Events::EventPayloadBuilder.build_orchestration_payload(
710
+ event_type: event_type,
711
+ context: context
712
+ )
713
+ end
714
+ end
715
+ end
716
+ end