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,328 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Tasker
4
+ module Analysis
5
+ # Analyzes step template dependencies for workflow design validation
6
+ #
7
+ # This class provides comprehensive analysis of step template dependencies,
8
+ # including cycle detection, topological sorting, and dependency visualization.
9
+ # It's designed to help with workflow design validation and troubleshooting.
10
+ #
11
+ # The analyzer performs static analysis on step templates to identify potential
12
+ # issues before workflow execution, including circular dependencies, dependency
13
+ # depth analysis, and parallel execution opportunities.
14
+ #
15
+ # @example Basic usage
16
+ # analyzer = TemplateGraphAnalyzer.new(handler.step_templates)
17
+ # graph = analyzer.analyze
18
+ # puts "Cycles detected: #{graph[:cycles].any?}"
19
+ #
20
+ # @example Checking for specific issues
21
+ # analyzer = TemplateGraphAnalyzer.new(templates)
22
+ # if analyzer.has_cycles?
23
+ # puts "Circular dependencies found: #{analyzer.cycles}"
24
+ # end
25
+ #
26
+ # @since 2.2.0
27
+ class TemplateGraphAnalyzer
28
+ # @return [Array<Tasker::Types::StepTemplate>] The step templates being analyzed
29
+ attr_reader :templates
30
+
31
+ # Initialize the analyzer with step templates
32
+ #
33
+ # @param templates [Array<Tasker::Types::StepTemplate>] Step templates to analyze
34
+ def initialize(templates)
35
+ @templates = templates
36
+ @dependency_map = nil
37
+ @analysis_cache = nil
38
+ end
39
+
40
+ # Perform comprehensive dependency analysis
41
+ #
42
+ # @return [Hash] Comprehensive dependency analysis containing:
43
+ # - :nodes - Array of step information with dependencies
44
+ # - :edges - Array of dependency relationships
45
+ # - :topology - Topologically sorted step names
46
+ # - :cycles - Array of detected circular dependencies
47
+ # - :levels - Hash mapping steps to their dependency depth levels
48
+ # - :roots - Array of steps with no dependencies
49
+ # - :leaves - Array of steps with no dependents
50
+ # - :summary - Summary statistics
51
+ def analyze
52
+ return @analysis_cache if @analysis_cache
53
+
54
+ nodes = build_nodes
55
+ edges = build_edges
56
+ dependency_map = build_dependency_map
57
+ cycles = detect_cycles(dependency_map)
58
+ topology = cycles.empty? ? topological_sort(dependency_map) : []
59
+ levels = calculate_dependency_levels(dependency_map, topology)
60
+ roots = find_root_steps
61
+ leaves = find_leaf_steps(edges)
62
+
63
+ @analysis_cache = {
64
+ nodes: nodes,
65
+ edges: edges,
66
+ topology: topology,
67
+ cycles: cycles,
68
+ levels: levels,
69
+ roots: roots,
70
+ leaves: leaves,
71
+ summary: build_summary(cycles, levels, edges)
72
+ }
73
+ end
74
+
75
+ # Check if the workflow has circular dependencies
76
+ #
77
+ # @return [Boolean] True if cycles are detected
78
+ def has_cycles?
79
+ cycles.any?
80
+ end
81
+
82
+ # Get detected circular dependencies
83
+ #
84
+ # @return [Array<Array<String>>] Array of detected cycles
85
+ def cycles
86
+ analyze[:cycles]
87
+ end
88
+
89
+ # Get topological ordering of steps
90
+ #
91
+ # @return [Array<String>] Topologically sorted step names
92
+ def topology
93
+ analyze[:topology]
94
+ end
95
+
96
+ # Get dependency levels for all steps
97
+ #
98
+ # @return [Hash<String, Integer>] Step name to dependency level mapping
99
+ def levels
100
+ analyze[:levels]
101
+ end
102
+
103
+ # Get steps with no dependencies (workflow entry points)
104
+ #
105
+ # @return [Array<String>] Root step names
106
+ def roots
107
+ analyze[:roots]
108
+ end
109
+
110
+ # Get steps with no dependents (workflow exit points)
111
+ #
112
+ # @return [Array<String>] Leaf step names
113
+ def leaves
114
+ analyze[:leaves]
115
+ end
116
+
117
+ # Clear analysis cache (useful if templates change)
118
+ #
119
+ # @return [void]
120
+ def clear_cache!
121
+ @analysis_cache = nil
122
+ @dependency_map = nil
123
+ end
124
+
125
+ private
126
+
127
+ # Build nodes with dependency information
128
+ #
129
+ # @return [Array<Hash>] Node information for each step
130
+ # @api private
131
+ def build_nodes
132
+ templates.map do |template|
133
+ {
134
+ name: template.name,
135
+ description: template.description,
136
+ handler_class: template.handler_class.name,
137
+ dependencies: template.all_dependencies,
138
+ dependency_count: template.all_dependencies.size
139
+ }
140
+ end
141
+ end
142
+
143
+ # Build edges (dependency relationships)
144
+ #
145
+ # @return [Array<Hash>] Edge information for dependencies
146
+ # @api private
147
+ def build_edges
148
+ edges = []
149
+ templates.each do |template|
150
+ template.all_dependencies.each do |dependency|
151
+ edges << {
152
+ from: dependency,
153
+ to: template.name,
154
+ type: template.depends_on_step == dependency ? 'single' : 'multiple'
155
+ }
156
+ end
157
+ end
158
+ edges
159
+ end
160
+
161
+ # Build dependency map from step templates
162
+ #
163
+ # @return [Hash<String, Array<String>>] Map of step name to its dependencies
164
+ # @api private
165
+ def build_dependency_map
166
+ return @dependency_map if @dependency_map
167
+
168
+ @dependency_map = templates.each_with_object({}) do |template, map|
169
+ map[template.name] = template.all_dependencies
170
+ end
171
+ end
172
+
173
+ # Detect circular dependencies using depth-first search
174
+ #
175
+ # @param dependency_map [Hash<String, Array<String>>] Step dependencies
176
+ # @return [Array<Array<String>>] Array of detected cycles
177
+ # @api private
178
+ def detect_cycles(dependency_map)
179
+ cycles = []
180
+ visited = Set.new
181
+ rec_stack = Set.new
182
+
183
+ dependency_map.each_key do |step|
184
+ next if visited.include?(step)
185
+
186
+ cycle = find_cycle_from_step(step, dependency_map, visited, rec_stack, [])
187
+ cycles << cycle if cycle
188
+ end
189
+
190
+ cycles
191
+ end
192
+
193
+ # Find cycle starting from a specific step
194
+ #
195
+ # @param step [String] Starting step name
196
+ # @param dependency_map [Hash] Step dependencies
197
+ # @param visited [Set] Visited steps
198
+ # @param rec_stack [Set] Recursion stack
199
+ # @param path [Array] Current path
200
+ # @return [Array<String>, nil] Cycle path or nil
201
+ # @api private
202
+ def find_cycle_from_step(step, dependency_map, visited, rec_stack, path)
203
+ return nil if visited.include?(step)
204
+
205
+ visited.add(step)
206
+ rec_stack.add(step)
207
+ current_path = path + [step]
208
+
209
+ dependency_map[step].each do |dependency|
210
+ if rec_stack.include?(dependency)
211
+ # Found cycle - return the cycle portion
212
+ cycle_start = current_path.index(dependency)
213
+ return current_path[cycle_start..] + [dependency]
214
+ end
215
+
216
+ cycle = find_cycle_from_step(dependency, dependency_map, visited, rec_stack, current_path)
217
+ return cycle if cycle
218
+ end
219
+
220
+ rec_stack.delete(step)
221
+ nil
222
+ end
223
+
224
+ # Perform topological sort of steps using Kahn's algorithm
225
+ #
226
+ # @param dependency_map [Hash<String, Array<String>>] Step dependencies
227
+ # @return [Array<String>] Topologically sorted step names
228
+ # @api private
229
+ def topological_sort(dependency_map)
230
+ in_degree = Hash.new(0)
231
+ reverse_deps = Hash.new { |h, k| h[k] = [] }
232
+
233
+ # Calculate in-degrees and reverse dependencies
234
+ dependency_map.each do |step, dependencies|
235
+ in_degree[step] ||= 0
236
+ dependencies.each do |dep|
237
+ in_degree[step] += 1
238
+ reverse_deps[dep] << step
239
+ end
240
+ end
241
+
242
+ # Start with steps that have no dependencies
243
+ queue = dependency_map.keys.select { |step| in_degree[step].zero? }
244
+ result = []
245
+
246
+ while queue.any?
247
+ current = queue.shift
248
+ result << current
249
+
250
+ # Remove edges from current step to its dependents
251
+ reverse_deps[current].each do |dependent|
252
+ in_degree[dependent] -= 1
253
+ queue << dependent if in_degree[dependent].zero?
254
+ end
255
+ end
256
+
257
+ result
258
+ end
259
+
260
+ # Calculate dependency levels for each step
261
+ #
262
+ # @param dependency_map [Hash<String, Array<String>>] Step dependencies
263
+ # @param topology [Array<String>] Topologically sorted steps
264
+ # @return [Hash<String, Integer>] Step name to dependency level
265
+ # @api private
266
+ def calculate_dependency_levels(dependency_map, topology)
267
+ levels = {}
268
+
269
+ topology.each do |step|
270
+ if dependency_map[step].empty?
271
+ levels[step] = 0
272
+ else
273
+ max_dependency_level = dependency_map[step].map { |dep| levels[dep] || 0 }.max
274
+ levels[step] = max_dependency_level + 1
275
+ end
276
+ end
277
+
278
+ levels
279
+ end
280
+
281
+ # Find steps with no dependencies
282
+ #
283
+ # @return [Array<String>] Root step names
284
+ # @api private
285
+ def find_root_steps
286
+ dependency_map = build_dependency_map
287
+ dependency_map.keys.select { |name| dependency_map[name].empty? }
288
+ end
289
+
290
+ # Find steps with no dependents
291
+ #
292
+ # @param edges [Array<Hash>] Dependency edges
293
+ # @return [Array<String>] Leaf step names
294
+ # @api private
295
+ def find_leaf_steps(edges)
296
+ step_names = templates.map(&:name)
297
+ step_names.reject { |name| edges.any? { |edge| edge[:from] == name } }
298
+ end
299
+
300
+ # Build summary statistics
301
+ #
302
+ # @param cycles [Array] Detected cycles
303
+ # @param levels [Hash] Dependency levels
304
+ # @param edges [Array] Dependency edges
305
+ # @return [Hash] Summary statistics
306
+ # @api private
307
+ def build_summary(cycles, levels, edges)
308
+ {
309
+ total_steps: templates.size,
310
+ total_dependencies: edges.size,
311
+ has_cycles: cycles.any?,
312
+ max_depth: levels.values.max || 0,
313
+ parallel_branches: count_parallel_branches(levels)
314
+ }
315
+ end
316
+
317
+ # Count parallel branches in the dependency graph
318
+ #
319
+ # @param levels [Hash<String, Integer>] Dependency levels
320
+ # @return [Integer] Number of parallel execution branches
321
+ # @api private
322
+ def count_parallel_branches(levels)
323
+ level_counts = levels.values.group_by(&:itself).transform_values(&:size)
324
+ level_counts.values.max || 1
325
+ end
326
+ end
327
+ end
328
+ end
@@ -0,0 +1,78 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'errors'
4
+ require_relative 'none_authenticator'
5
+
6
+ module Tasker
7
+ module Authentication
8
+ class Coordinator
9
+ class << self
10
+ def authenticator
11
+ @authenticator ||= build_authenticator
12
+ end
13
+
14
+ delegate :authenticate!, to: :authenticator
15
+
16
+ delegate :current_user, to: :authenticator
17
+
18
+ delegate :authenticated?, to: :authenticator
19
+
20
+ def reset!
21
+ @authenticator = nil
22
+ end
23
+
24
+ private
25
+
26
+ def build_authenticator
27
+ auth_config = Tasker.configuration.auth
28
+
29
+ if auth_config.authentication_enabled
30
+ build_custom_authenticator(auth_config)
31
+ else
32
+ NoneAuthenticator.new
33
+ end
34
+ end
35
+
36
+ def build_custom_authenticator(auth_config)
37
+ authenticator_class = auth_config.authenticator_class
38
+
39
+ unless authenticator_class
40
+ raise ConfigurationError,
41
+ 'Authentication is enabled but no authenticator_class is specified'
42
+ end
43
+
44
+ # Instantiate the host app's authenticator
45
+ klass = authenticator_class.constantize
46
+ # Pass empty options hash for now - authenticators can get config from Tasker.configuration
47
+ authenticator = klass.new({})
48
+
49
+ # Validate it implements the interface
50
+ validate_authenticator!(authenticator)
51
+
52
+ authenticator
53
+ end
54
+
55
+ def validate_authenticator!(authenticator)
56
+ required_methods = %i[authenticate! current_user]
57
+
58
+ required_methods.each do |method|
59
+ unless authenticator.respond_to?(method)
60
+ raise InterfaceError,
61
+ "Authenticator #{authenticator.class} must implement ##{method}"
62
+ end
63
+ end
64
+
65
+ # Run configuration validation if supported
66
+ return unless authenticator.respond_to?(:validate_configuration)
67
+
68
+ # Pass configuration options for validation - authenticators can extract what they need
69
+ errors = authenticator.validate_configuration({})
70
+ return unless errors.any?
71
+
72
+ raise ConfigurationError,
73
+ "Authenticator configuration errors: #{errors.join(', ')}"
74
+ end
75
+ end
76
+ end
77
+ end
78
+ end
@@ -0,0 +1,9 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Tasker
4
+ module Authentication
5
+ class AuthenticationError < StandardError; end
6
+ class ConfigurationError < StandardError; end
7
+ class InterfaceError < StandardError; end
8
+ end
9
+ end
@@ -0,0 +1,36 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Tasker
4
+ module Authentication
5
+ # Interface that host application authenticators must implement
6
+ module Interface
7
+ # Required: Authenticate the request, raise exception if fails
8
+ # @param controller [ActionController::Base] The controller instance
9
+ # @return [void] Should raise exception on authentication failure
10
+ def authenticate!(controller)
11
+ raise NotImplementedError, 'Authenticator must implement #authenticate!'
12
+ end
13
+
14
+ # Required: Get the current authenticated user
15
+ # @param controller [ActionController::Base] The controller instance
16
+ # @return [Object, nil] The authenticated user object or nil
17
+ def current_user(controller)
18
+ raise NotImplementedError, 'Authenticator must implement #current_user'
19
+ end
20
+
21
+ # Optional: Check if user is authenticated (uses current_user by default)
22
+ # @param controller [ActionController::Base] The controller instance
23
+ # @return [Boolean] true if authenticated, false otherwise
24
+ def authenticated?(controller)
25
+ current_user(controller).present?
26
+ end
27
+
28
+ # Optional: Configuration validation for the authenticator
29
+ # @param _options [Hash] Configuration options (unused in default implementation)
30
+ # @return [Array<String>] Array of validation error messages, empty if valid
31
+ def validate_configuration(_options = {})
32
+ []
33
+ end
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,26 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'interface'
4
+
5
+ module Tasker
6
+ module Authentication
7
+ class NoneAuthenticator
8
+ include Interface
9
+
10
+ def authenticate!(_controller)
11
+ # No authentication required - always succeeds
12
+ true
13
+ end
14
+
15
+ def current_user(_controller)
16
+ # No user in no-auth mode
17
+ nil
18
+ end
19
+
20
+ def authenticated?(_controller)
21
+ # Always considered "authenticated" in no-auth mode
22
+ true
23
+ end
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,112 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Tasker
4
+ module Authorization
5
+ # Base authorization coordinator providing the foundation for authorization logic.
6
+ #
7
+ # This class implements the core authorization interface that can be extended
8
+ # by host applications to provide custom authorization logic. It follows the
9
+ # same dependency injection pattern as the authentication system.
10
+ #
11
+ # Host applications should inherit from this class and implement the
12
+ # `authorized?` method to provide their authorization logic.
13
+ #
14
+ # @example Basic usage
15
+ # coordinator = BaseCoordinator.new(current_user)
16
+ # coordinator.authorize!('tasker.task', :show, { task_id: 123 })
17
+ #
18
+ # @example Custom implementation
19
+ # class MyAuthorizationCoordinator < BaseCoordinator
20
+ # protected
21
+ #
22
+ # def authorized?(resource, action, context = {})
23
+ # case resource
24
+ # when 'tasker.task'
25
+ # user.can_access_tasks?
26
+ # else
27
+ # false
28
+ # end
29
+ # end
30
+ # end
31
+ class BaseCoordinator
32
+ # Initialize the authorization coordinator
33
+ #
34
+ # @param user [Object, nil] The user object to authorize against
35
+ def initialize(user = nil)
36
+ @user = user
37
+ end
38
+
39
+ # Authorize an action and raise an exception if not permitted
40
+ #
41
+ # This method checks authorization and raises an UnauthorizedError
42
+ # if the action is not permitted.
43
+ #
44
+ # @param resource [String] The resource being accessed (e.g., 'tasker.task')
45
+ # @param action [Symbol, String] The action being performed (e.g., :show)
46
+ # @param context [Hash] Additional context for authorization decisions
47
+ # @raise [UnauthorizedError] When the action is not authorized
48
+ # @return [true] When the action is authorized
49
+ def authorize!(resource, action, context = {})
50
+ unless can?(resource, action, context)
51
+ raise UnauthorizedError,
52
+ "Not authorized to #{action} on #{resource}"
53
+ end
54
+
55
+ true
56
+ end
57
+
58
+ # Check if an action is authorized
59
+ #
60
+ # This method performs the authorization check without raising an exception.
61
+ # It validates the resource and action exist, then delegates to the
62
+ # `authorized?` method for the actual authorization logic.
63
+ #
64
+ # @param resource [String] The resource being accessed
65
+ # @param action [Symbol, String] The action being performed
66
+ # @param context [Hash] Additional context for authorization decisions
67
+ # @return [Boolean] True if the action is authorized
68
+ def can?(resource, action, context = {})
69
+ # Allow all actions if authorization is disabled
70
+ return true unless authorization_enabled?
71
+
72
+ # Validate resource and action exist in the registry
73
+ unless ResourceRegistry.action_exists?(resource, action)
74
+ raise ArgumentError, "Unknown resource:action '#{resource}:#{action}'"
75
+ end
76
+
77
+ # Delegate to subclass implementation
78
+ authorized?(resource, action, context)
79
+ end
80
+
81
+ protected
82
+
83
+ # Authorization logic to be implemented by subclasses
84
+ #
85
+ # This method should be overridden by host applications to provide
86
+ # their specific authorization logic. The default implementation
87
+ # denies all access.
88
+ #
89
+ # @param _resource [String] The resource being accessed (unused in base implementation)
90
+ # @param _action [Symbol, String] The action being performed (unused in base implementation)
91
+ # @param _context [Hash] Additional context for authorization decisions (unused in base implementation)
92
+ # @return [Boolean] True if the action should be authorized
93
+ def authorized?(_resource, _action, _context = {})
94
+ # Default implementation: deny all access
95
+ # Subclasses should override this method
96
+ false
97
+ end
98
+
99
+ # Check if authorization is enabled in the configuration
100
+ #
101
+ # @return [Boolean] True if authorization is enabled
102
+ def authorization_enabled?
103
+ Tasker.configuration.auth.authorization_enabled
104
+ end
105
+
106
+ # The user object for authorization checks
107
+ #
108
+ # @return [Object, nil] The current user
109
+ attr_reader :user
110
+ end
111
+ end
112
+ end
@@ -0,0 +1,26 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Tasker
4
+ module Authorization
5
+ # Base error class for all authorization-related errors
6
+ class AuthorizationError < StandardError; end
7
+
8
+ # Raised when a user is not authorized to perform a specific action
9
+ #
10
+ # This error should be raised when authorization checks fail, typically
11
+ # resulting in a 403 Forbidden HTTP response.
12
+ #
13
+ # @example
14
+ # raise UnauthorizedError, "Not authorized to delete task 123"
15
+ class UnauthorizedError < AuthorizationError; end
16
+
17
+ # Raised when authorization configuration is invalid
18
+ #
19
+ # This error indicates problems with the authorization setup, such as
20
+ # missing coordinator classes or invalid configuration options.
21
+ #
22
+ # @example
23
+ # raise ConfigurationError, "Authorization coordinator class 'InvalidClass' not found"
24
+ class ConfigurationError < AuthorizationError; end
25
+ end
26
+ end
@@ -0,0 +1,74 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Tasker
4
+ module Authorization
5
+ # Constants for authorization resource names and actions.
6
+ #
7
+ # This module provides centralized constants for all authorization
8
+ # resource identifiers, making the codebase more maintainable and
9
+ # reducing the risk of typos in resource strings.
10
+ #
11
+ # @example Using resource constants
12
+ # coordinator.authorize!(RESOURCES::TASK, ACTIONS::SHOW)
13
+ # ResourceRegistry.resource_exists?(RESOURCES::WORKFLOW_STEP)
14
+ module ResourceConstants
15
+ # Resource name constants
16
+ module RESOURCES
17
+ TASK = 'tasker.task'
18
+ WORKFLOW_STEP = 'tasker.workflow_step'
19
+ TASK_DIAGRAM = 'tasker.task_diagram'
20
+ HEALTH_STATUS = 'tasker.health_status'
21
+ HANDLER = 'tasker.handler'
22
+ METRICS = 'tasker.metrics'
23
+ ANALYTICS = 'tasker.analytics'
24
+
25
+ # Get all resource constants as an array
26
+ #
27
+ # @return [Array<String>] All defined resource names
28
+ def self.all
29
+ [TASK, WORKFLOW_STEP, TASK_DIAGRAM, HEALTH_STATUS, HANDLER, METRICS, ANALYTICS]
30
+ end
31
+
32
+ # Check if a resource constant is defined
33
+ #
34
+ # @param resource [String] Resource name to check
35
+ # @return [Boolean] True if the resource is defined
36
+ def self.include?(resource)
37
+ all.include?(resource)
38
+ end
39
+ end
40
+
41
+ # Common action constants used across resources
42
+ module ACTIONS
43
+ INDEX = :index
44
+ SHOW = :show
45
+ CREATE = :create
46
+ UPDATE = :update
47
+ DESTROY = :destroy
48
+ RETRY = :retry
49
+ CANCEL = :cancel
50
+
51
+ # Standard CRUD actions
52
+ #
53
+ # @return [Array<Symbol>] Standard CRUD action symbols
54
+ def self.crud
55
+ [INDEX, SHOW, CREATE, UPDATE, DESTROY]
56
+ end
57
+
58
+ # Task-specific actions
59
+ #
60
+ # @return [Array<Symbol>] Actions specific to tasks
61
+ def self.task_specific
62
+ [RETRY, CANCEL]
63
+ end
64
+
65
+ # All defined actions
66
+ #
67
+ # @return [Array<Symbol>] All action constants
68
+ def self.all
69
+ [INDEX, SHOW, CREATE, UPDATE, DESTROY, RETRY, CANCEL]
70
+ end
71
+ end
72
+ end
73
+ end
74
+ end