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,381 @@
1
+ # typed: false
2
+ # frozen_string_literal: true
3
+
4
+ require_relative '../concerns/structured_logging'
5
+
6
+ module Tasker
7
+ module Registry
8
+ # Comprehensive statistics collection for all registry systems
9
+ #
10
+ # Provides unified observability, performance monitoring, and
11
+ # health checking across all registry components.
12
+ class StatisticsCollector
13
+ include Tasker::Concerns::StructuredLogging
14
+
15
+ class << self
16
+ # Collect comprehensive statistics from all registries
17
+ #
18
+ # @return [Hash] Complete statistics for all registries
19
+ def collect_all_registry_stats
20
+ registries = discover_all_registries
21
+
22
+ stats = {
23
+ collection_timestamp: Time.current,
24
+ total_registries: registries.size,
25
+ registries: {}
26
+ }
27
+
28
+ registries.each do |registry|
29
+ registry_stats = collect_registry_stats(registry)
30
+ stats[:registries][registry_stats[:registry_name]] = registry_stats
31
+ end
32
+
33
+ # Calculate aggregated metrics
34
+ stats[:aggregated] = calculate_aggregated_metrics(stats[:registries])
35
+
36
+ stats
37
+ end
38
+
39
+ # Collect statistics from a specific registry
40
+ #
41
+ # @param registry [BaseRegistry] Registry to collect stats from
42
+ # @return [Hash] Registry statistics with performance metrics
43
+ def collect_registry_stats(registry)
44
+ base_stats = registry.stats
45
+ health_check = registry.health_check
46
+
47
+ {
48
+ **base_stats,
49
+ health: health_check,
50
+ performance: measure_registry_performance(registry),
51
+ usage_patterns: analyze_usage_patterns(registry),
52
+ recommendations: generate_recommendations(registry)
53
+ }
54
+ end
55
+
56
+ # Get health status for all registries
57
+ #
58
+ # @return [Hash] Health status summary
59
+ def health_summary
60
+ registries = discover_all_registries
61
+
62
+ health_results = registries.map do |registry|
63
+ {
64
+ registry_name: registry.class.name.demodulize.underscore,
65
+ healthy: registry.healthy?,
66
+ health_details: registry.health_check
67
+ }
68
+ end
69
+
70
+ {
71
+ overall_healthy: health_results.all? { |result| result[:healthy] },
72
+ registry_count: registries.size,
73
+ healthy_registries: health_results.count { |result| result[:healthy] },
74
+ unhealthy_registries: health_results.reject { |result| result[:healthy] },
75
+ registries: health_results,
76
+ checked_at: Time.current
77
+ }
78
+ end
79
+
80
+ # Find registries matching criteria
81
+ #
82
+ # @param criteria [Hash] Search criteria
83
+ # @option criteria [String] :name_pattern Registry name pattern
84
+ # @option criteria [Symbol] :health_status Health status filter (:healthy, :unhealthy)
85
+ # @option criteria [Integer] :min_items Minimum item count
86
+ # @return [Array<BaseRegistry>] Matching registries
87
+ def find_registries(criteria = {})
88
+ registries = discover_all_registries
89
+
90
+ if criteria[:name_pattern]
91
+ pattern = Regexp.new(criteria[:name_pattern], Regexp::IGNORECASE)
92
+ registries = registries.select { |registry| registry.class.name.match?(pattern) }
93
+ end
94
+
95
+ if criteria[:health_status]
96
+ case criteria[:health_status]
97
+ when :healthy
98
+ registries = registries.select(&:healthy?)
99
+ when :unhealthy
100
+ registries = registries.reject(&:healthy?)
101
+ end
102
+ end
103
+
104
+ if criteria[:min_items]
105
+ registries = registries.select do |registry|
106
+ registry.stats[:total_handlers] ||
107
+ registry.stats[:total_plugins] ||
108
+ registry.stats[:total_subscribers] || criteria[:min_items] <= 0
109
+ end
110
+ end
111
+
112
+ registries
113
+ end
114
+
115
+ # Generate performance report
116
+ #
117
+ # @return [Hash] Performance analysis across all registries
118
+ def performance_report
119
+ registries = discover_all_registries
120
+
121
+ performance_data = registries.map do |registry|
122
+ {
123
+ registry_name: registry.class.name.demodulize.underscore,
124
+ performance: measure_registry_performance(registry),
125
+ item_count: calculate_registry_item_count(registry)
126
+ }
127
+ end
128
+
129
+ {
130
+ report_timestamp: Time.current,
131
+ total_registries: registries.size,
132
+ performance_data: performance_data,
133
+ performance_summary: calculate_performance_summary(performance_data)
134
+ }
135
+ end
136
+
137
+ private
138
+
139
+ # Discover all available registries
140
+ #
141
+ # @return [Array<BaseRegistry>] All registry instances
142
+ def discover_all_registries
143
+ registries = []
144
+
145
+ # Core registries
146
+ registries << Tasker::HandlerFactory.instance if defined?(Tasker::HandlerFactory)
147
+ registries << Tasker::Registry::SubscriberRegistry.instance if defined?(Tasker::Registry::SubscriberRegistry)
148
+
149
+ # Telemetry registries
150
+ if defined?(Tasker::Telemetry)
151
+ registries << Tasker::Telemetry::PluginRegistry.instance if defined?(Tasker::Telemetry::PluginRegistry)
152
+ if defined?(Tasker::Telemetry::ExportCoordinator)
153
+ registries << Tasker::Telemetry::ExportCoordinator.instance
154
+ end
155
+ end
156
+
157
+ registries.compact
158
+ end
159
+
160
+ # Measure performance metrics for a registry
161
+ #
162
+ # @param registry [BaseRegistry] Registry to measure
163
+ # @return [Hash] Performance metrics
164
+ def measure_registry_performance(registry)
165
+ # Measure stats collection time
166
+ stats_start = Process.clock_gettime(Process::CLOCK_MONOTONIC)
167
+ registry.stats
168
+ stats_duration = Process.clock_gettime(Process::CLOCK_MONOTONIC) - stats_start
169
+
170
+ # Measure health check time
171
+ health_start = Process.clock_gettime(Process::CLOCK_MONOTONIC)
172
+ registry.health_check
173
+ health_duration = Process.clock_gettime(Process::CLOCK_MONOTONIC) - health_start
174
+
175
+ {
176
+ stats_response_time_ms: (stats_duration * 1000).round(2),
177
+ health_check_time_ms: (health_duration * 1000).round(2),
178
+ thread_safe: true,
179
+ last_measured: Time.current
180
+ }
181
+ end
182
+
183
+ # Analyze usage patterns for a registry
184
+ #
185
+ # @param registry [BaseRegistry] Registry to analyze
186
+ # @return [Hash] Usage pattern analysis
187
+ def analyze_usage_patterns(registry)
188
+ stats = registry.stats
189
+
190
+ {
191
+ utilization: calculate_utilization(stats),
192
+ distribution: calculate_distribution(stats),
193
+ growth_trend: 'stable', # Would track over time in production
194
+ efficiency_score: calculate_efficiency_score(stats)
195
+ }
196
+ end
197
+
198
+ # Calculate utilization level
199
+ #
200
+ # @param stats [Hash] Registry statistics
201
+ # @return [String] Utilization level
202
+ def calculate_utilization(stats)
203
+ total_items = stats[:total_handlers] || stats[:total_plugins] || stats[:total_subscribers] || 0
204
+
205
+ case total_items
206
+ when 0 then 'empty'
207
+ when 1..5 then 'low'
208
+ when 6..20 then 'medium'
209
+ when 21..50 then 'high'
210
+ else 'very_high'
211
+ end
212
+ end
213
+
214
+ # Calculate distribution pattern
215
+ #
216
+ # @param stats [Hash] Registry statistics
217
+ # @return [String] Distribution pattern
218
+ def calculate_distribution(stats)
219
+ if stats[:handlers_by_namespace]
220
+ analyze_namespace_distribution(stats[:handlers_by_namespace])
221
+ elsif stats[:plugins_by_format]
222
+ analyze_format_distribution(stats[:plugins_by_format])
223
+ elsif stats[:subscribers_by_event]
224
+ analyze_event_distribution(stats[:subscribers_by_event])
225
+ else
226
+ 'unknown'
227
+ end
228
+ end
229
+
230
+ # Analyze namespace distribution for handlers
231
+ #
232
+ # @param handlers_by_namespace [Hash] Handler distribution data
233
+ # @return [String] Distribution pattern
234
+ def analyze_namespace_distribution(handlers_by_namespace)
235
+ return 'empty' if handlers_by_namespace.empty?
236
+
237
+ values = handlers_by_namespace.values
238
+ return 'single' if values.size == 1
239
+
240
+ avg = values.sum.to_f / values.size
241
+ variance = values.sum { |v| (v - avg)**2 } / values.size
242
+
243
+ variance < 2 ? 'even' : 'skewed'
244
+ end
245
+
246
+ # Analyze format distribution for plugins
247
+ #
248
+ # @param plugins_by_format [Hash] Plugin distribution data
249
+ # @return [String] Distribution pattern
250
+ def analyze_format_distribution(plugins_by_format)
251
+ return 'empty' if plugins_by_format.empty?
252
+
253
+ values = plugins_by_format.values
254
+ values.uniq.size == 1 ? 'uniform' : 'varied'
255
+ end
256
+
257
+ # Analyze event distribution for subscribers
258
+ #
259
+ # @param subscribers_by_event [Hash] Subscriber distribution data
260
+ # @return [String] Distribution pattern
261
+ def analyze_event_distribution(subscribers_by_event)
262
+ return 'empty' if subscribers_by_event.empty?
263
+
264
+ values = subscribers_by_event.values
265
+ avg = values.sum.to_f / values.size
266
+ variance = values.sum { |v| (v - avg)**2 } / values.size
267
+
268
+ variance < 1 ? 'balanced' : 'unbalanced'
269
+ end
270
+
271
+ # Calculate efficiency score
272
+ #
273
+ # @param stats [Hash] Registry statistics
274
+ # @return [Float] Efficiency score (0.0 - 1.0)
275
+ def calculate_efficiency_score(stats)
276
+ # Simple efficiency calculation based on utilization and distribution
277
+ base_score = 0.5
278
+
279
+ # Adjust for utilization
280
+ utilization = calculate_utilization(stats)
281
+ utilization_bonus = case utilization
282
+ when 'empty' then -0.3
283
+ when 'low' then 0.0
284
+ when 'medium' then 0.2
285
+ when 'high' then 0.3
286
+ when 'very_high' then 0.1
287
+ end
288
+
289
+ # Adjust for distribution
290
+ distribution = calculate_distribution(stats)
291
+ distribution_bonus = case distribution
292
+ when 'even', 'balanced', 'uniform' then 0.2
293
+ when 'skewed', 'unbalanced', 'varied' then -0.1
294
+ else 0.0
295
+ end
296
+
297
+ [0.0, [1.0, base_score + utilization_bonus + distribution_bonus].min].max
298
+ end
299
+
300
+ # Generate recommendations for a registry
301
+ #
302
+ # @param registry [BaseRegistry] Registry to analyze
303
+ # @return [Array<String>] Recommendations
304
+ def generate_recommendations(registry)
305
+ recommendations = []
306
+ stats = registry.stats
307
+
308
+ # Health recommendations
309
+ recommendations << 'Registry health check failed - investigate immediately' unless registry.healthy?
310
+
311
+ # Utilization recommendations
312
+ utilization = calculate_utilization(stats)
313
+ case utilization
314
+ when 'empty'
315
+ recommendations << "Registry is empty - consider if it's needed"
316
+ when 'very_high'
317
+ recommendations << 'High utilization - monitor performance and consider optimization'
318
+ end
319
+
320
+ # Distribution recommendations
321
+ distribution = calculate_distribution(stats)
322
+ case distribution
323
+ when 'skewed', 'unbalanced'
324
+ recommendations << 'Uneven distribution detected - consider rebalancing'
325
+ end
326
+
327
+ recommendations.empty? ? ['Registry is operating optimally'] : recommendations
328
+ end
329
+
330
+ # Calculate aggregated metrics across all registries
331
+ #
332
+ # @param registries_stats [Hash] Statistics for all registries
333
+ # @return [Hash] Aggregated metrics
334
+ def calculate_aggregated_metrics(registries_stats)
335
+ total_items = 0
336
+ healthy_count = 0
337
+ efficiency_scores = []
338
+
339
+ registries_stats.each_value do |stats|
340
+ total_items += stats[:total_handlers] || stats[:total_plugins] || stats[:total_subscribers] || 0
341
+ healthy_count += 1 if stats[:health][:healthy]
342
+ efficiency_scores << stats[:usage_patterns][:efficiency_score]
343
+ end
344
+
345
+ {
346
+ total_registered_items: total_items,
347
+ overall_health_percentage: registries_stats.empty? ? 0 : (healthy_count.to_f / registries_stats.size * 100).round(1),
348
+ average_efficiency_score: efficiency_scores.empty? ? 0 : (efficiency_scores.sum / efficiency_scores.size).round(3),
349
+ registry_count: registries_stats.size
350
+ }
351
+ end
352
+
353
+ # Calculate item count for a registry
354
+ #
355
+ # @param registry [BaseRegistry] Registry to count items for
356
+ # @return [Integer] Total item count
357
+ def calculate_registry_item_count(registry)
358
+ stats = registry.stats
359
+ stats[:total_handlers] || stats[:total_plugins] || stats[:total_subscribers] || 0
360
+ end
361
+
362
+ # Calculate performance summary
363
+ #
364
+ # @param performance_data [Array<Hash>] Performance data for all registries
365
+ # @return [Hash] Performance summary
366
+ def calculate_performance_summary(performance_data)
367
+ response_times = performance_data.map { |data| data[:performance][:stats_response_time_ms] }
368
+
369
+ return { summary: 'no_data' } if response_times.empty?
370
+
371
+ {
372
+ average_response_time_ms: (response_times.sum / response_times.size).round(2),
373
+ max_response_time_ms: response_times.max,
374
+ min_response_time_ms: response_times.min,
375
+ total_items_managed: performance_data.sum { |data| data[:item_count] }
376
+ }
377
+ end
378
+ end
379
+ end
380
+ end
381
+ end
@@ -0,0 +1,285 @@
1
+ # typed: false
2
+ # frozen_string_literal: true
3
+
4
+ require_relative 'base_registry'
5
+ require_relative 'interface_validator'
6
+ require 'concurrent-ruby'
7
+
8
+ module Tasker
9
+ module Registry
10
+ # Registry for managing event subscribers
11
+ #
12
+ # Provides centralized management of event subscribers with discovery,
13
+ # registration, and event-based lookup capabilities. Integrates with
14
+ # the existing event system to provide comprehensive subscriber coordination.
15
+ #
16
+ # @example Register a subscriber
17
+ # registry = Tasker::Registry::SubscriberRegistry.instance
18
+ # registry.register(MySubscriber, events: ['task.created', 'task.completed'])
19
+ #
20
+ # @example Find subscribers for an event
21
+ # subscribers = registry.subscribers_for_event('task.created')
22
+ #
23
+ # @example Auto-discover subscribers
24
+ # registry.auto_discover_subscribers
25
+ class SubscriberRegistry < BaseRegistry
26
+ include Singleton
27
+
28
+ def initialize
29
+ super
30
+ @subscribers = Concurrent::Hash.new
31
+ @event_mappings = Concurrent::Hash.new
32
+ log_registry_operation('initialized', total_subscribers: 0, total_events: 0)
33
+ end
34
+
35
+ # Register an event subscriber
36
+ #
37
+ # @param subscriber_class [Class] The subscriber class to register
38
+ # @param events [Array<String>] Events this subscriber handles
39
+ # @param replace [Boolean] Whether to replace existing subscriber
40
+ # @param options [Hash] Additional registration options
41
+ # @return [Boolean] True if registration successful
42
+ # @raise [ArgumentError] If subscriber already exists and replace is false
43
+ def register(subscriber_class, events: [], replace: false, **options)
44
+ subscriber_name = subscriber_class.name.demodulize.underscore
45
+
46
+ thread_safe_operation do
47
+ # Validate subscriber interface
48
+ begin
49
+ Registry::InterfaceValidator.validate_subscriber!(subscriber_class)
50
+ rescue ArgumentError => e
51
+ log_validation_failure('event_subscriber', subscriber_name, e.message)
52
+ raise
53
+ end
54
+
55
+ # Check for existing subscriber
56
+ if @subscribers.key?(subscriber_name) && !replace
57
+ raise ArgumentError, "Subscriber '#{subscriber_name}' already registered. Use replace: true to override."
58
+ end
59
+
60
+ # Remove existing subscriber if replacing
61
+ if @subscribers.key?(subscriber_name)
62
+ existing_config = @subscribers[subscriber_name]
63
+ unregister_event_mappings(subscriber_name, existing_config[:events])
64
+ log_unregistration('event_subscriber', subscriber_name, existing_config[:subscriber_class])
65
+ end
66
+
67
+ # Register subscriber
68
+ subscriber_config = {
69
+ subscriber_class: subscriber_class,
70
+ events: events,
71
+ registered_at: Time.current,
72
+ options: options.merge(replace: replace)
73
+ }
74
+
75
+ @subscribers[subscriber_name] = subscriber_config
76
+
77
+ # Index by events
78
+ register_event_mappings(subscriber_name, events)
79
+
80
+ log_registration('event_subscriber', subscriber_name, subscriber_class,
81
+ { events: events, event_count: events.size, **options })
82
+
83
+ true
84
+ end
85
+ end
86
+
87
+ # Unregister an event subscriber
88
+ #
89
+ # @param subscriber_class [Class, String] The subscriber class or name to unregister
90
+ # @return [Boolean] True if unregistered successfully
91
+ def unregister(subscriber_class)
92
+ subscriber_name = if subscriber_class.is_a?(Class)
93
+ subscriber_class.name.demodulize.underscore
94
+ else
95
+ subscriber_class.to_s
96
+ end
97
+
98
+ thread_safe_operation do
99
+ subscriber_config = @subscribers.delete(subscriber_name)
100
+
101
+ if subscriber_config
102
+ # Remove from event mappings
103
+ unregister_event_mappings(subscriber_name, subscriber_config[:events])
104
+
105
+ log_unregistration('event_subscriber', subscriber_name, subscriber_config[:subscriber_class])
106
+ true
107
+ else
108
+ false
109
+ end
110
+ end
111
+ end
112
+
113
+ # Get subscribers for a specific event
114
+ #
115
+ # @param event_name [String] The event name to find subscribers for
116
+ # @return [Array<Hash>] Array of subscriber configurations
117
+ def subscribers_for_event(event_name)
118
+ subscriber_names = @event_mappings[event_name.to_s] || []
119
+ subscriber_names.filter_map { |name| @subscribers[name] }
120
+ end
121
+
122
+ # Get all registered subscribers
123
+ #
124
+ # @return [Hash] All registered subscribers
125
+ def all_subscribers
126
+ @subscribers.dup
127
+ end
128
+
129
+ # Get all registered subscribers (required by BaseRegistry)
130
+ #
131
+ # @return [Hash] All registered subscribers
132
+ def all_items
133
+ all_subscribers
134
+ end
135
+
136
+ # Get supported events across all subscribers
137
+ #
138
+ # @return [Array<String>] Array of supported event names
139
+ def supported_events
140
+ @event_mappings.keys.sort
141
+ end
142
+
143
+ # Check if an event has any subscribers
144
+ #
145
+ # @param event_name [String] Event name to check
146
+ # @return [Boolean] True if event has subscribers
147
+ def has_subscribers?(event_name)
148
+ @event_mappings.key?(event_name.to_s) && !@event_mappings[event_name.to_s].empty?
149
+ end
150
+
151
+ # Auto-discover subscribers in the subscribers directory
152
+ #
153
+ # @param directory [String] Directory to search for subscribers
154
+ # @return [Integer] Number of subscribers discovered
155
+ def auto_discover_subscribers(directory = nil)
156
+ directory ||= File.join(File.dirname(__FILE__), '..', 'events', 'subscribers')
157
+
158
+ return 0 unless Dir.exist?(directory)
159
+
160
+ discovered_count = 0
161
+
162
+ Dir.glob(File.join(directory, '*_subscriber.rb')).each do |file|
163
+ require file
164
+
165
+ # Extract class name from filename
166
+ class_name = File.basename(file, '.rb').camelize
167
+ full_class_name = "Tasker::Events::Subscribers::#{class_name}"
168
+
169
+ begin
170
+ # Try to instantiate the subscriber
171
+ subscriber_class = full_class_name.constantize
172
+
173
+ # Auto-discover events from class methods or constants
174
+ events = discover_subscriber_events(subscriber_class)
175
+
176
+ register(subscriber_class, events: events, auto_discovered: true)
177
+ discovered_count += 1
178
+
179
+ log_registry_operation('auto_discovered_subscriber',
180
+ subscriber_name: subscriber_class.name,
181
+ events: events,
182
+ file_path: file)
183
+ rescue StandardError => e
184
+ log_registry_error('auto_discovery_failed', e,
185
+ file_path: file,
186
+ class_name: full_class_name)
187
+ end
188
+ end
189
+
190
+ discovered_count
191
+ end
192
+
193
+ # Get comprehensive registry statistics
194
+ #
195
+ # @return [Hash] Detailed statistics about the registry
196
+ def stats
197
+ base_stats.merge(
198
+ total_subscribers: @subscribers.size,
199
+ total_events: @event_mappings.size,
200
+ events_covered: @event_mappings.keys.sort,
201
+ subscribers_by_event: @event_mappings.transform_values(&:size),
202
+ average_events_per_subscriber: calculate_average_events_per_subscriber,
203
+ most_popular_events: find_most_popular_events
204
+ )
205
+ end
206
+
207
+ # Clear all registered subscribers (required by BaseRegistry)
208
+ #
209
+ # @return [Boolean] True if cleared successfully
210
+ def clear!
211
+ thread_safe_operation do
212
+ @subscribers.clear
213
+ @event_mappings.clear
214
+ log_registry_operation('cleared_all')
215
+ true
216
+ end
217
+ end
218
+
219
+ private
220
+
221
+ # Register event mappings for a subscriber
222
+ #
223
+ # @param subscriber_name [String] Name of the subscriber
224
+ # @param events [Array<String>] Events to map
225
+ def register_event_mappings(subscriber_name, events)
226
+ events.each do |event|
227
+ event_key = event.to_s
228
+ @event_mappings[event_key] ||= []
229
+ @event_mappings[event_key] << subscriber_name unless @event_mappings[event_key].include?(subscriber_name)
230
+ end
231
+ end
232
+
233
+ # Unregister event mappings for a subscriber
234
+ #
235
+ # @param subscriber_name [String] Name of the subscriber
236
+ # @param events [Array<String>] Events to unmap
237
+ def unregister_event_mappings(subscriber_name, events)
238
+ events.each do |event|
239
+ event_key = event.to_s
240
+ @event_mappings[event_key]&.delete(subscriber_name)
241
+ @event_mappings.delete(event_key) if @event_mappings[event_key] && @event_mappings[event_key].empty?
242
+ end
243
+ end
244
+
245
+ # Discover events that a subscriber handles
246
+ #
247
+ # @param subscriber_class [Class] The subscriber class to analyze
248
+ # @return [Array<String>] Array of event names
249
+ def discover_subscriber_events(subscriber_class)
250
+ events = []
251
+
252
+ # Check for EVENTS constant
253
+ events.concat(Array(subscriber_class::EVENTS)) if subscriber_class.const_defined?(:EVENTS)
254
+
255
+ # Check for events class method
256
+ events.concat(Array(subscriber_class.events)) if subscriber_class.respond_to?(:events)
257
+
258
+ # Check for event_patterns class method
259
+ events.concat(Array(subscriber_class.event_patterns)) if subscriber_class.respond_to?(:event_patterns)
260
+
261
+ events.map(&:to_s).uniq
262
+ end
263
+
264
+ # Calculate average events per subscriber
265
+ #
266
+ # @return [Float] Average number of events per subscriber
267
+ def calculate_average_events_per_subscriber
268
+ return 0.0 if @subscribers.empty?
269
+
270
+ total_events = @subscribers.values.sum { |config| config[:events].size }
271
+ (total_events.to_f / @subscribers.size).round(2)
272
+ end
273
+
274
+ # Find the most popular events (top 5)
275
+ #
276
+ # @return [Array<Hash>] Array of event popularity data
277
+ def find_most_popular_events
278
+ @event_mappings
279
+ .map { |event, subscribers| { event: event, subscriber_count: subscribers.size } }
280
+ .sort_by { |data| -data[:subscriber_count] }
281
+ .first(5)
282
+ end
283
+ end
284
+ end
285
+ end
@@ -0,0 +1,22 @@
1
+ # typed: false
2
+ # frozen_string_literal: true
3
+
4
+ # Registry module for Tasker
5
+ #
6
+ # Provides unified registry management with thread-safe operations,
7
+ # validation, observability, and coordination capabilities.
8
+ module Tasker
9
+ module Registry
10
+ # Registry-related errors
11
+ class RegistryError < StandardError; end
12
+ class ValidationError < RegistryError; end
13
+ class RegistrationError < RegistryError; end
14
+ end
15
+ end
16
+
17
+ # Require all registry components
18
+ require_relative 'registry/base_registry'
19
+ require_relative 'registry/interface_validator'
20
+ require_relative 'registry/event_publisher'
21
+ require_relative 'registry/subscriber_registry'
22
+ require_relative 'registry/statistics_collector'