pg_eventstore 2.0.0 → 3.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 (303) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop.yml +10 -1
  3. data/CHANGELOG.md +186 -20
  4. data/README.md +25 -15
  5. data/db/migrations/10_setup_pg_cron.rb +1 -23
  6. data/db/migrations/15_create_streams_global_index.sql +17 -0
  7. data/db/migrations/16_populate_streams_global_index.rb +150 -0
  8. data/db/migrations/17_create_events_global_index.sql +62 -0
  9. data/db/migrations/18_populate_events_global_index.rb +124 -0
  10. data/db/migrations/19_populate_events_global_index_p2.rb +25 -0
  11. data/db/migrations/20_migrate_subscriptions_current_position.sql +19 -0
  12. data/db/migrations/21_create_partitions_stats.sql +2 -0
  13. data/db/migrations/22_drop_streams_sql_view.sql +2 -0
  14. data/db/migrations/23_adjust_partitions_indexes.sql +5 -0
  15. data/db/migrations/24_drop_legacy_events_indexes.sql +3 -0
  16. data/db/migrations/25_add_parent_partitions_info_to_partitions.sql +16 -0
  17. data/db/migrations/26_change_events_stream_revision_type.rb +35 -0
  18. data/db/migrations/27_drop_events_horizon.sql +3 -0
  19. data/db/migrations/28_create_maintenance_tasks.sql +8 -0
  20. data/db/migrations/29_create_event_markers.sql +35 -0
  21. data/db/migrations/30_improve_partitions_search_in_admin_ui.rb +24 -0
  22. data/db/migrations/31_drop_events_id_default_value.sql +1 -0
  23. data/db/migrations/32_create_parittions_triggers.sql +101 -0
  24. data/docs/AGENTS.fragment.md +696 -0
  25. data/docs/admin_ui.md +3 -1
  26. data/docs/appending_events.md +110 -49
  27. data/docs/configuration.md +69 -36
  28. data/docs/event_tracing.md +55 -0
  29. data/docs/events_and_streams.md +54 -30
  30. data/docs/how_it_works.md +57 -16
  31. data/docs/linking_events.md +2 -1
  32. data/docs/maintenance.md +14 -5
  33. data/docs/multiple_commands.md +17 -8
  34. data/docs/reading_events.md +208 -43
  35. data/docs/reading_streams.md +50 -0
  36. data/docs/replication.md +99 -0
  37. data/docs/subscriptions.md +165 -35
  38. data/docs/writing_middleware.md +25 -8
  39. data/ext/pg_eventstore_ext/extconf.rb +5 -0
  40. data/ext/pg_eventstore_ext/pg_eventstore_ext.c +74 -0
  41. data/lib/pg_eventstore/async_runner.rb +63 -0
  42. data/lib/pg_eventstore/basic_config.rb +15 -0
  43. data/lib/pg_eventstore/chunks/chunk.rb +31 -0
  44. data/lib/pg_eventstore/chunks/read_api_events_index_chunk.rb +83 -0
  45. data/lib/pg_eventstore/chunks/replica_events_index_chunk.rb +35 -0
  46. data/lib/pg_eventstore/chunks/repository.rb +73 -0
  47. data/lib/pg_eventstore/chunks/subscription_checkpoint_chunk.rb +48 -0
  48. data/lib/pg_eventstore/chunks/subscription_events_index_chunk.rb +99 -0
  49. data/lib/pg_eventstore/chunks.rb +14 -0
  50. data/lib/pg_eventstore/client.rb +163 -50
  51. data/lib/pg_eventstore/commands/append.rb +62 -43
  52. data/lib/pg_eventstore/commands/delete_event.rb +7 -8
  53. data/lib/pg_eventstore/commands/delete_stream.rb +3 -3
  54. data/lib/pg_eventstore/commands/event_modifiers/prepare_link_event.rb +9 -7
  55. data/lib/pg_eventstore/commands/event_modifiers/prepare_regular_event.rb +12 -7
  56. data/lib/pg_eventstore/commands/link_to.rb +5 -5
  57. data/lib/pg_eventstore/commands/read.rb +23 -5
  58. data/lib/pg_eventstore/commands/read_grouped.rb +46 -0
  59. data/lib/pg_eventstore/commands/read_streams.rb +18 -0
  60. data/lib/pg_eventstore/commands/read_streams_paginated.rb +56 -0
  61. data/lib/pg_eventstore/commands/regular_stream_read_paginated.rb +4 -4
  62. data/lib/pg_eventstore/commands/revision_check/current_revision.rb +51 -0
  63. data/lib/pg_eventstore/commands/revision_check/event_type_revisions_comparison.rb +46 -0
  64. data/lib/pg_eventstore/commands/revision_check/expected_revision.rb +135 -0
  65. data/lib/pg_eventstore/commands/revision_check/stream_revision_check.rb +98 -0
  66. data/lib/pg_eventstore/commands/revision_check/stream_revision_comparison.rb +36 -0
  67. data/lib/pg_eventstore/commands/stream_revision.rb +14 -0
  68. data/lib/pg_eventstore/commands/system_stream_read_paginated.rb +4 -4
  69. data/lib/pg_eventstore/commands.rb +4 -2
  70. data/lib/pg_eventstore/config.rb +30 -9
  71. data/lib/pg_eventstore/connection.rb +21 -2
  72. data/lib/pg_eventstore/errors.rb +136 -10
  73. data/lib/pg_eventstore/event.rb +34 -2
  74. data/lib/pg_eventstore/event_deserializer.rb +5 -4
  75. data/lib/pg_eventstore/event_global_index.rb +118 -0
  76. data/lib/pg_eventstore/event_marker.rb +16 -0
  77. data/lib/pg_eventstore/event_marker_index.rb +25 -0
  78. data/lib/pg_eventstore/event_serializer.rb +6 -0
  79. data/lib/pg_eventstore/extensions/acts_as_configurable.rb +88 -0
  80. data/lib/pg_eventstore/extensions/options_defaults.rb +25 -0
  81. data/lib/pg_eventstore/extensions/options_extension.rb +2 -2
  82. data/lib/pg_eventstore/feature_marker.rb +18 -0
  83. data/lib/pg_eventstore/maintenance.rb +11 -6
  84. data/lib/pg_eventstore/middleware/event_tracing.rb +53 -0
  85. data/lib/pg_eventstore/partition.rb +6 -0
  86. data/lib/pg_eventstore/pg_connection.rb +70 -14
  87. data/lib/pg_eventstore/queries/event_marker_queries.rb +74 -0
  88. data/lib/pg_eventstore/queries/event_queries.rb +7 -93
  89. data/lib/pg_eventstore/queries/events_global_index_queries.rb +131 -0
  90. data/lib/pg_eventstore/queries/index_filtering_queries.rb +179 -0
  91. data/lib/pg_eventstore/queries/links_resolver.rb +4 -4
  92. data/lib/pg_eventstore/queries/maintenance_queries.rb +159 -42
  93. data/lib/pg_eventstore/queries/partition_queries.rb +45 -103
  94. data/lib/pg_eventstore/queries/replica_queries.rb +110 -0
  95. data/lib/pg_eventstore/queries/streams_global_index_queries.rb +163 -0
  96. data/lib/pg_eventstore/queries/transaction_queries.rb +52 -10
  97. data/lib/pg_eventstore/queries.rb +29 -1
  98. data/lib/pg_eventstore/query_builders/basic_filtering.rb +38 -5
  99. data/lib/pg_eventstore/query_builders/event_markers_filtering.rb +47 -0
  100. data/lib/pg_eventstore/query_builders/event_markers_index_filtering.rb +275 -0
  101. data/lib/pg_eventstore/query_builders/event_subscription_positions_filtering.rb +37 -0
  102. data/lib/pg_eventstore/query_builders/events_filtering.rb +15 -164
  103. data/lib/pg_eventstore/query_builders/events_global_index_filtering.rb +227 -0
  104. data/lib/pg_eventstore/query_builders/filters/collection.rb +324 -0
  105. data/lib/pg_eventstore/query_builders/filters/event_type_filter.rb +37 -0
  106. data/lib/pg_eventstore/query_builders/filters/filter_row.rb +54 -0
  107. data/lib/pg_eventstore/query_builders/filters/marker_filter.rb +20 -0
  108. data/lib/pg_eventstore/query_builders/filters/marker_filter_row.rb +49 -0
  109. data/lib/pg_eventstore/query_builders/filters/stream_filter.rb +48 -0
  110. data/lib/pg_eventstore/query_builders/index_based_events_filtering.rb +260 -0
  111. data/lib/pg_eventstore/query_builders/partitions_filtering.rb +175 -51
  112. data/lib/pg_eventstore/query_builders/read_cursor/stream_cursor.rb +122 -0
  113. data/lib/pg_eventstore/query_builders/streams_global_index_filtering.rb +83 -0
  114. data/lib/pg_eventstore/query_builders/subscription_events_filtering.rb +79 -0
  115. data/lib/pg_eventstore/query_strategy/async.rb +64 -0
  116. data/lib/pg_eventstore/query_strategy/foreground.rb +25 -0
  117. data/lib/pg_eventstore/query_strategy.rb +19 -0
  118. data/lib/pg_eventstore/raw_event.rb +46 -0
  119. data/lib/pg_eventstore/rspec/test_helpers.rb +21 -8
  120. data/lib/pg_eventstore/sql_builder.rb +87 -8
  121. data/lib/pg_eventstore/stream.rb +13 -16
  122. data/lib/pg_eventstore/stream_global_index.rb +28 -0
  123. data/lib/pg_eventstore/subscriptions/callback_handlers/events_processor_handlers.rb +5 -17
  124. data/lib/pg_eventstore/subscriptions/callback_handlers/events_subscription_position_worker_handlers.rb +36 -0
  125. data/lib/pg_eventstore/subscriptions/callback_handlers/subscription_feeder_handlers.rb +12 -0
  126. data/lib/pg_eventstore/subscriptions/callback_handlers/subscription_runner_handlers.rb +21 -7
  127. data/lib/pg_eventstore/subscriptions/events_processor.rb +20 -18
  128. data/lib/pg_eventstore/subscriptions/events_processor_consumer/multiple.rb +63 -0
  129. data/lib/pg_eventstore/subscriptions/events_processor_consumer/replica.rb +68 -0
  130. data/lib/pg_eventstore/subscriptions/events_processor_consumer/single.rb +62 -0
  131. data/lib/pg_eventstore/subscriptions/events_processor_consumer.rb +44 -0
  132. data/lib/pg_eventstore/subscriptions/events_subscription_position_worker.rb +68 -0
  133. data/lib/pg_eventstore/subscriptions/queries/event_subscription_position_queries.rb +177 -0
  134. data/lib/pg_eventstore/subscriptions/queries/subscription_queries.rb +78 -54
  135. data/lib/pg_eventstore/subscriptions/replica_subscription_handler.rb +140 -0
  136. data/lib/pg_eventstore/subscriptions/replica_subscription_runner.rb +9 -0
  137. data/lib/pg_eventstore/subscriptions/subscription.rb +2 -1
  138. data/lib/pg_eventstore/subscriptions/subscription_feed_strategies/collection.rb +36 -0
  139. data/lib/pg_eventstore/subscriptions/subscription_feed_strategies/index_read_strategy.rb +82 -0
  140. data/lib/pg_eventstore/subscriptions/subscription_feed_strategies/replication_strategy.rb +75 -0
  141. data/lib/pg_eventstore/subscriptions/subscription_feed_strategy.rb +31 -0
  142. data/lib/pg_eventstore/subscriptions/subscription_feeder.rb +24 -0
  143. data/lib/pg_eventstore/subscriptions/subscription_handler_performance.rb +4 -2
  144. data/lib/pg_eventstore/subscriptions/subscription_runner.rb +20 -9
  145. data/lib/pg_eventstore/subscriptions/subscription_runner_commands/reset_position.rb +1 -1
  146. data/lib/pg_eventstore/subscriptions/subscription_runners_feeder.rb +9 -18
  147. data/lib/pg_eventstore/subscriptions/subscriptions_lifecycle.rb +0 -12
  148. data/lib/pg_eventstore/subscriptions/subscriptions_manager.rb +74 -14
  149. data/lib/pg_eventstore/{subscriptions/synchronized_array.rb → synchronized_array.rb} +15 -0
  150. data/lib/pg_eventstore/tasks/setup.rake +2 -2
  151. data/lib/pg_eventstore/utils.rb +31 -0
  152. data/lib/pg_eventstore/version.rb +1 -1
  153. data/lib/pg_eventstore/web/application.rb +100 -16
  154. data/lib/pg_eventstore/web/paginator/base_collection.rb +5 -1
  155. data/lib/pg_eventstore/web/paginator/event_types_collection.rb +14 -4
  156. data/lib/pg_eventstore/web/paginator/events_collection.rb +29 -33
  157. data/lib/pg_eventstore/web/paginator/helpers.rb +16 -9
  158. data/lib/pg_eventstore/web/paginator/markers_collection.rb +48 -0
  159. data/lib/pg_eventstore/web/paginator/stream_contexts_collection.rb +13 -2
  160. data/lib/pg_eventstore/web/paginator/stream_ids_collection.rb +21 -11
  161. data/lib/pg_eventstore/web/paginator/stream_names_collection.rb +18 -4
  162. data/lib/pg_eventstore/web/paginator/streams_collection.rb +95 -0
  163. data/lib/pg_eventstore/web/public/javascripts/pg_eventstore.js +49 -22
  164. data/lib/pg_eventstore/web/subscriptions/set_collection.rb +1 -1
  165. data/lib/pg_eventstore/web/subscriptions/subscriptions.rb +1 -1
  166. data/lib/pg_eventstore/web/subscriptions/with_state/set_collection.rb +1 -1
  167. data/lib/pg_eventstore/web/subscriptions/with_state/subscriptions.rb +1 -1
  168. data/lib/pg_eventstore/web/views/home/dashboard.erb +11 -9
  169. data/lib/pg_eventstore/web/views/home/partials/event_filter.erb +18 -5
  170. data/lib/pg_eventstore/web/views/home/partials/events.erb +38 -1
  171. data/lib/pg_eventstore/web/views/home/partials/markers_filter.erb +18 -0
  172. data/lib/pg_eventstore/web/views/layouts/application.erb +6 -0
  173. data/lib/pg_eventstore/web/views/streams/index.erb +110 -0
  174. data/lib/pg_eventstore/web/views/streams/partials/streams.erb +11 -0
  175. data/lib/pg_eventstore/web/views/subscriptions/index.erb +4 -1
  176. data/lib/pg_eventstore/web.rb +2 -0
  177. data/lib/pg_eventstore.rb +23 -60
  178. data/pg_eventstore.gemspec +6 -4
  179. data/sig/interfaces/_raw_events_handler.rbs +3 -0
  180. data/sig/interfaces/subscription_handler.rbs +1 -1
  181. data/sig/pg/result.rbs +9 -0
  182. data/sig/pg_eventstore/async_runner.rbs +13 -0
  183. data/sig/pg_eventstore/basic_config.rbs +9 -0
  184. data/sig/pg_eventstore/chunks/chunk.rbs +13 -0
  185. data/sig/pg_eventstore/chunks/read_api_events_index_chunk.rbs +30 -0
  186. data/sig/pg_eventstore/chunks/replica_events_index_chunk.rbs +11 -0
  187. data/sig/pg_eventstore/chunks/repository.rbs +22 -0
  188. data/sig/pg_eventstore/chunks/subscription_checkpoint_chunk.rbs +18 -0
  189. data/sig/pg_eventstore/chunks/subscription_events_index_chunk.rbs +37 -0
  190. data/sig/pg_eventstore/client.rbs +40 -42
  191. data/sig/pg_eventstore/commands/append.rbs +11 -25
  192. data/sig/pg_eventstore/commands/event_modifiers/prepare_link_event.rbs +9 -12
  193. data/sig/pg_eventstore/commands/event_modifiers/prepare_regular_event.rbs +5 -4
  194. data/sig/pg_eventstore/commands/link_to.rbs +6 -11
  195. data/sig/pg_eventstore/commands/read.rbs +2 -5
  196. data/sig/pg_eventstore/commands/read_grouped.rbs +7 -0
  197. data/sig/pg_eventstore/commands/read_streams.rbs +7 -0
  198. data/sig/pg_eventstore/commands/read_streams_paginated.rbs +16 -0
  199. data/sig/pg_eventstore/commands/regular_stream_read_paginated.rbs +9 -17
  200. data/sig/pg_eventstore/commands/revision_check/current_revision.rbs +25 -0
  201. data/sig/pg_eventstore/commands/revision_check/event_type_revisions_comparison.rbs +14 -0
  202. data/sig/pg_eventstore/commands/revision_check/expected_revision.rbs +67 -0
  203. data/sig/pg_eventstore/commands/revision_check/stream_revision_check.rbs +20 -0
  204. data/sig/pg_eventstore/commands/revision_check/stream_revision_comparison.rbs +9 -0
  205. data/sig/pg_eventstore/commands/stream_revision.rbs +7 -0
  206. data/sig/pg_eventstore/commands/system_stream_read_paginated.rbs +9 -14
  207. data/sig/pg_eventstore/config.rbs +15 -6
  208. data/sig/pg_eventstore/connection.rbs +11 -18
  209. data/sig/pg_eventstore/errors.rbs +64 -34
  210. data/sig/pg_eventstore/event.rbs +16 -2
  211. data/sig/pg_eventstore/event_deserializer.rbs +5 -10
  212. data/sig/pg_eventstore/event_global_index.rbs +60 -0
  213. data/sig/pg_eventstore/event_marker.rbs +9 -0
  214. data/sig/pg_eventstore/event_marker_index.rbs +12 -0
  215. data/sig/pg_eventstore/extensions/acts_as_configurable.rbs +29 -0
  216. data/sig/pg_eventstore/extensions/options_defaults.rbs +7 -0
  217. data/sig/pg_eventstore/feature_marker.rbs +10 -0
  218. data/sig/pg_eventstore/maintenance.rbs +12 -8
  219. data/sig/pg_eventstore/middleware/event_trace.rbs +14 -0
  220. data/sig/pg_eventstore/partition.rbs +2 -4
  221. data/sig/pg_eventstore/pg_connection.rbs +8 -0
  222. data/sig/pg_eventstore/queries/event_marker_queries.rbs +21 -0
  223. data/sig/pg_eventstore/queries/event_queries.rbs +4 -36
  224. data/sig/pg_eventstore/queries/events_global_index_queries.rbs +37 -0
  225. data/sig/pg_eventstore/queries/index_filtering_queries.rbs +50 -0
  226. data/sig/pg_eventstore/queries/links_resolver.rbs +5 -9
  227. data/sig/pg_eventstore/queries/maintenance_queries.rbs +12 -9
  228. data/sig/pg_eventstore/queries/partition_queries.rbs +32 -67
  229. data/sig/pg_eventstore/queries/replica_queries.rbs +31 -0
  230. data/sig/pg_eventstore/queries/streams_global_index_queries.rbs +39 -0
  231. data/sig/pg_eventstore/queries/transaction_queries.rbs +2 -0
  232. data/sig/pg_eventstore/queries.rbs +11 -21
  233. data/sig/pg_eventstore/query_builders/basic_filtering.rbs +10 -3
  234. data/sig/pg_eventstore/query_builders/event_markers_filtering.rbs +17 -0
  235. data/sig/pg_eventstore/query_builders/event_markers_index_filtering.rbs +69 -0
  236. data/sig/pg_eventstore/query_builders/event_subscription_positions_filtering.rbs +15 -0
  237. data/sig/pg_eventstore/query_builders/events_filtering_query.rbs +9 -51
  238. data/sig/pg_eventstore/query_builders/events_global_index_filtering.rbs +68 -0
  239. data/sig/pg_eventstore/query_builders/filters/collection.rbs +84 -0
  240. data/sig/pg_eventstore/query_builders/filters/event_type_filter.rbs +19 -0
  241. data/sig/pg_eventstore/query_builders/filters/filter_row.rbs +21 -0
  242. data/sig/pg_eventstore/query_builders/filters/marker_filter.rbs +13 -0
  243. data/sig/pg_eventstore/query_builders/filters/marker_filter_row.rbs +19 -0
  244. data/sig/pg_eventstore/query_builders/filters/stream_filter.rbs +24 -0
  245. data/sig/pg_eventstore/query_builders/index_based_events_filtering.rbs +60 -0
  246. data/sig/pg_eventstore/query_builders/partitions_filtering.rbs +29 -10
  247. data/sig/pg_eventstore/query_builders/read_cursor/stream_cursor.rbs +47 -0
  248. data/sig/pg_eventstore/query_builders/streams_global_index_filtering.rbs +27 -0
  249. data/sig/pg_eventstore/query_builders/subscription_events_filtering.rbs +26 -0
  250. data/sig/pg_eventstore/query_strategy/async.rbs +17 -0
  251. data/sig/pg_eventstore/query_strategy/foreground.rbs +11 -0
  252. data/sig/pg_eventstore/query_strategy.rbs +7 -0
  253. data/sig/pg_eventstore/raw_event.rbs +20 -0
  254. data/sig/pg_eventstore/sql_builder.rbs +32 -10
  255. data/sig/pg_eventstore/stream.rbs +10 -18
  256. data/sig/pg_eventstore/stream_global_index.rbs +14 -0
  257. data/sig/pg_eventstore/subscriptions/callback_handlers/events_processor_handlers.rbs +5 -4
  258. data/sig/pg_eventstore/subscriptions/callback_handlers/events_subscription_position_worker_handlers.rbs +9 -0
  259. data/sig/pg_eventstore/subscriptions/callback_handlers/subscription_feeder_handlers.rbs +17 -12
  260. data/sig/pg_eventstore/subscriptions/callback_handlers/subscription_runner_handlers.rbs +17 -6
  261. data/sig/pg_eventstore/subscriptions/event_subscription_position_queries.rbs +30 -0
  262. data/sig/pg_eventstore/subscriptions/events_processor.rbs +12 -5
  263. data/sig/pg_eventstore/subscriptions/events_processor_consumer/multiple.rbs +17 -0
  264. data/sig/pg_eventstore/subscriptions/events_processor_consumer/replica.rbs +17 -0
  265. data/sig/pg_eventstore/subscriptions/events_processor_consumer/single.rbs +17 -0
  266. data/sig/pg_eventstore/subscriptions/events_processor_consumer.rbs +14 -0
  267. data/sig/pg_eventstore/subscriptions/events_subscription_position_worker.rbs +28 -0
  268. data/sig/pg_eventstore/subscriptions/queries/subscription_queries.rbs +7 -39
  269. data/sig/pg_eventstore/subscriptions/replica_subscription_handler.rbs +33 -0
  270. data/sig/pg_eventstore/subscriptions/replica_subscription_runner.rbs +4 -0
  271. data/sig/pg_eventstore/subscriptions/subscription_feed_strategy/collection.rbs +14 -0
  272. data/sig/pg_eventstore/subscriptions/subscription_feed_strategy/index_read_strategy.rbs +23 -0
  273. data/sig/pg_eventstore/subscriptions/subscription_feed_strategy/replication_strategy.rbs +23 -0
  274. data/sig/pg_eventstore/subscriptions/subscription_feed_strategy.rbs +11 -0
  275. data/sig/pg_eventstore/subscriptions/subscription_feeder.rbs +13 -10
  276. data/sig/pg_eventstore/subscriptions/subscription_handler_performance.rbs +1 -1
  277. data/sig/pg_eventstore/subscriptions/subscription_runner.rbs +13 -2
  278. data/sig/pg_eventstore/subscriptions/subscription_runners_feeder.rbs +1 -8
  279. data/sig/pg_eventstore/subscriptions/subscriptions_lifecycle.rbs +4 -6
  280. data/sig/pg_eventstore/subscriptions/subscriptions_manager.rbs +29 -43
  281. data/sig/pg_eventstore/synchronized_array.rbs +4 -0
  282. data/sig/pg_eventstore/utils.rbs +10 -11
  283. data/sig/pg_eventstore/web/application.rbs +13 -3
  284. data/sig/pg_eventstore/web/paginator/base_collection.rbs +2 -0
  285. data/sig/pg_eventstore/web/paginator/event_types_collection.rbs +4 -0
  286. data/sig/pg_eventstore/web/paginator/events_collection.rbs +11 -11
  287. data/sig/pg_eventstore/web/paginator/helpers.rbs +6 -15
  288. data/sig/pg_eventstore/web/paginator/markers_collection.rbs +13 -0
  289. data/sig/pg_eventstore/web/paginator/stream_contexts_collection.rbs +4 -0
  290. data/sig/pg_eventstore/web/paginator/stream_names_collection.rbs +4 -0
  291. data/sig/pg_eventstore/web/paginator/streams_collection.rbs +30 -0
  292. data/sig/pg_eventstore.rbs +8 -26
  293. metadata +175 -20
  294. data/Dockerfile +0 -3
  295. data/lib/pg_eventstore/commands/all_stream_read_grouped.rb +0 -69
  296. data/lib/pg_eventstore/commands/regular_stream_read_grouped.rb +0 -31
  297. data/lib/pg_eventstore/subscriptions/queries/subscription_service_queries.rb +0 -78
  298. data/lib/pg_eventstore/web/views/home/partials/system_stream_filter.erb +0 -15
  299. data/sig/pg_eventstore/commands/all_stream_read_grouped.rbs +0 -16
  300. data/sig/pg_eventstore/commands/regular_stream_read_grouped.rbs +0 -8
  301. data/sig/pg_eventstore/subscriptions/queries/subscription_service_queries.rbs +0 -19
  302. data/sig/pg_eventstore/subscriptions/synchronized_array.rbs +0 -4
  303. /data/sig/interfaces/{_raw_event_handler.rbs → raw_event_handler.rbs} +0 -0
@@ -0,0 +1,75 @@
1
+ # frozen_string_literal: true
2
+
3
+ module PgEventstore
4
+ module SubscriptionFeedStrategy
5
+ # @!visibility private
6
+ class ReplicationStrategy
7
+ include SubscriptionFeedStrategy
8
+
9
+ # Allow subscriptions to scan through up to this amount of events per a single query. This allows to make query
10
+ # plan more predictable.
11
+ # @return [Integer]
12
+ INDEX_LOOK_UP_DISTANCE = 100_000
13
+
14
+ # @param connection [PgEventstore::Connection]
15
+ # @param query_strategy [PgEventstore::QueryStrategy]
16
+ def initialize(connection, query_strategy)
17
+ @connection = connection
18
+ @query_strategy = query_strategy
19
+ @runners = []
20
+ end
21
+
22
+ # @param runners [Array<PgEventstore::ReplicaSubscriptionRunner>]
23
+ # @return [Array<PgEventstore::ReplicaSubscriptionRunner>]
24
+ def add(*runners)
25
+ @runners.push(*runners)
26
+ end
27
+
28
+ # @return [Integer]
29
+ def size
30
+ @runners.size
31
+ end
32
+
33
+ # @return [Boolean]
34
+ def any?
35
+ @runners.any?
36
+ end
37
+
38
+ # @return [void]
39
+ def feed
40
+ runners_query_options = @runners.to_h do |runner|
41
+ next_chunk_query_opts = runner.next_chunk_query_opts
42
+ next_chunk_query_opts[:to_position] =
43
+ [next_chunk_query_opts[:from_position] + INDEX_LOOK_UP_DISTANCE, safe_position].min
44
+ [runner.id, next_chunk_query_opts]
45
+ end
46
+ grouped_indexes = events_global_index_queries.fetch_indexes_for_subscriptions(runners_query_options)
47
+ @runners.each do |runner|
48
+ if grouped_indexes[runner.id]
49
+ chunk = Chunks::ReplicaEventsIndexChunk.new(grouped_indexes[runner.id])
50
+ runner.feed(chunk)
51
+ else
52
+ runner.feed(Chunks::SubscriptionCheckpointChunk.new(runners_query_options[runner.id][:to_position]))
53
+ end
54
+ end
55
+ end
56
+
57
+ private
58
+
59
+ # @return [Integer]
60
+ def safe_position
61
+ event_subscription_position_queries.max_subscription_position || 0
62
+ end
63
+
64
+ # @return [PgEventstore::EventsGlobalIndexQueries]
65
+ def events_global_index_queries
66
+ EventsGlobalIndexQueries.new(@connection, @query_strategy)
67
+ end
68
+
69
+ # @return [PgEventstore::EventSubscriptionPositionQueries]
70
+ def event_subscription_position_queries
71
+ EventSubscriptionPositionQueries.new(@connection)
72
+ end
73
+ end
74
+ end
75
+ end
@@ -0,0 +1,31 @@
1
+ # frozen_string_literal: true
2
+
3
+ module PgEventstore
4
+ # @!visibility private
5
+ module SubscriptionFeedStrategy
6
+ # @param runners [PgEventstore::SubscriptionRunner, Array<PgEventstore::SubscriptionRunner>]
7
+ # @return [Array<PgEventstore::SubscriptionRunner>]
8
+ def add(*runners)
9
+ raise NotImplementedError
10
+ end
11
+
12
+ # @return [Integer]
13
+ def size
14
+ raise NotImplementedError
15
+ end
16
+
17
+ # @return [Boolean]
18
+ def any?
19
+ raise NotImplementedError
20
+ end
21
+
22
+ # @return [void]
23
+ def feed
24
+ raise NotImplementedError
25
+ end
26
+ end
27
+ end
28
+
29
+ require_relative 'subscription_feed_strategies/collection'
30
+ require_relative 'subscription_feed_strategies/index_read_strategy'
31
+ require_relative 'subscription_feed_strategies/replication_strategy'
@@ -30,6 +30,9 @@ module PgEventstore
30
30
  @subscriptions_set_lifecycle = subscriptions_set_lifecycle
31
31
  @subscriptions_lifecycle = subscriptions_lifecycle
32
32
  @commands_handler = CommandsHandler.new(@config_name, self, @subscriptions_lifecycle.runners)
33
+ if requires_subscription_position_assignment?
34
+ @events_subscription_position_worker = EventsSubscriptionPositionWorker.new(@config_name)
35
+ end
33
36
  attach_runner_callbacks
34
37
  end
35
38
 
@@ -77,6 +80,14 @@ module PgEventstore
77
80
  :before_runner_started, :before,
78
81
  SubscriptionFeederHandlers.setup_handler(:start_cmds_handler, @commands_handler)
79
82
  )
83
+ if requires_subscription_position_assignment?
84
+ @basic_runner.define_callback(
85
+ :before_runner_started, :before,
86
+ SubscriptionFeederHandlers.setup_handler(
87
+ :start_events_subscription_position_worker, @events_subscription_position_worker
88
+ )
89
+ )
90
+ end
80
91
 
81
92
  @basic_runner.define_callback(
82
93
  :after_runner_died, :before,
@@ -108,6 +119,14 @@ module PgEventstore
108
119
  :after_runner_stopped, :before,
109
120
  SubscriptionFeederHandlers.setup_handler(:stop_commands_handler, @commands_handler)
110
121
  )
122
+ if requires_subscription_position_assignment?
123
+ @basic_runner.define_callback(
124
+ :after_runner_stopped, :before,
125
+ SubscriptionFeederHandlers.setup_handler(
126
+ :stop_events_subscription_position_worker, @events_subscription_position_worker
127
+ )
128
+ )
129
+ end
111
130
 
112
131
  @basic_runner.define_callback(
113
132
  :before_runner_restored, :after,
@@ -126,5 +145,10 @@ module PgEventstore
126
145
  ),
127
146
  ]
128
147
  end
148
+
149
+ # @return [Boolean]
150
+ def requires_subscription_position_assignment?
151
+ Config::NodeRole.writable.include?(PgEventstore.config(@config_name).eventstore_role)
152
+ end
129
153
  end
130
154
  end
@@ -8,7 +8,7 @@ module PgEventstore
8
8
  extend Forwardable
9
9
 
10
10
  # @return [Integer] the number of measurements to keep
11
- TIMINGS_TO_KEEP = 100
11
+ TIMINGS_TO_KEEP = 10
12
12
 
13
13
  def_delegators :@lock, :synchronize
14
14
 
@@ -18,10 +18,12 @@ module PgEventstore
18
18
  end
19
19
 
20
20
  # Yields the given block to measure its execution time
21
+ # @param events_number [Integer] number of events processed by the given block
21
22
  # @return [Object] the result of yielded block
22
- def track_exec_time
23
+ def track_exec_time(events_number)
23
24
  result = nil
24
25
  time = Utils.benchmark { result = yield }
26
+ time /= events_number
25
27
  synchronize do
26
28
  @timings.shift if @timings.size == TIMINGS_TO_KEEP
27
29
  @timings.push(time)
@@ -11,37 +11,43 @@ module PgEventstore
11
11
  extend Forwardable
12
12
 
13
13
  # @return [Integer]
14
- MAX_EVENTS_PER_CHUNK = 1_000
14
+ DEFAULT_MAX_EVENTS_PER_CHUNK = 1_000
15
15
  # @return [Integer]
16
16
  MIN_EVENTS_PER_CHUNK = 10
17
17
  # @return [Integer]
18
- INITIAL_EVENTS_PER_CHUNK = 10
18
+ DEFAULT_INITIAL_EVENTS_PER_CHUNK = 10
19
19
 
20
20
  # @!attribute subscription
21
21
  # @return [PgEventstore::Subscription]
22
22
  attr_reader :subscription
23
23
 
24
24
  def_delegators :@events_processor, :start, :stop, :stop_async, :feed, :wait_for_finish, :restore, :state, :running?,
25
- :clear_chunk, :within_state
25
+ :clear_events_repository, :within_state
26
26
  def_delegators :@subscription, :lock!, :id
27
27
 
28
28
  # @param stats [PgEventstore::SubscriptionHandlerPerformance]
29
29
  # @param events_processor [PgEventstore::EventsProcessor]
30
30
  # @param subscription [PgEventstore::Subscription]
31
- def initialize(stats:, events_processor:, subscription:)
31
+ # @param max_events_per_chunk [Integer]
32
+ def initialize(stats:, events_processor:, subscription:,
33
+ initial_events_per_chunk: DEFAULT_INITIAL_EVENTS_PER_CHUNK,
34
+ max_events_per_chunk: DEFAULT_MAX_EVENTS_PER_CHUNK)
32
35
  @stats = stats
33
36
  @events_processor = events_processor
34
37
  @subscription = subscription
38
+ @max_events_per_chunk = max_events_per_chunk
39
+ @initial_events_per_chunk = initial_events_per_chunk
35
40
 
36
41
  attach_callbacks
37
42
  end
38
43
 
39
44
  # @return [Hash]
40
45
  def next_chunk_query_opts
41
- @subscription.options.merge(
46
+ {
42
47
  from_position: next_chunk_global_position,
43
- max_count: estimate_events_number
44
- )
48
+ max_count: estimate_events_number,
49
+ resolve_link_tos: @subscription.options[:resolve_link_tos] || false,
50
+ }
45
51
  end
46
52
 
47
53
  # @return [Boolean]
@@ -61,10 +67,10 @@ module PgEventstore
61
67
 
62
68
  # @return [Integer]
63
69
  def estimate_events_number
64
- return INITIAL_EVENTS_PER_CHUNK if @stats.average_event_processing_time == 0
70
+ return @initial_events_per_chunk if @stats.average_event_processing_time == 0
65
71
 
66
72
  events_per_chunk = (@subscription.chunk_query_interval / @stats.average_event_processing_time).round
67
- events_to_fetch = [events_per_chunk, MAX_EVENTS_PER_CHUNK].min - @events_processor.events_left_in_chunk
73
+ events_to_fetch = [events_per_chunk, @max_events_per_chunk].min - @events_processor.events_left_in_repo
68
74
  return 0 if events_to_fetch < 0 # We still have a lot of events in the chunk - no need to fetch more
69
75
 
70
76
  [events_to_fetch, MIN_EVENTS_PER_CHUNK].max
@@ -91,6 +97,11 @@ module PgEventstore
91
97
  SubscriptionRunnerHandlers.setup_handler(:update_subscription_chunk_stats, @subscription)
92
98
  )
93
99
 
100
+ @events_processor.define_callback(
101
+ :checkpoint, :after,
102
+ SubscriptionRunnerHandlers.setup_handler(:checkpoint, @subscription)
103
+ )
104
+
94
105
  @events_processor.define_callback(
95
106
  :restart, :after,
96
107
  SubscriptionRunnerHandlers.setup_handler(:update_subscription_restarts, @subscription)
@@ -16,7 +16,7 @@ module PgEventstore
16
16
  # @return [void]
17
17
  def exec_cmd(subscription_runner)
18
18
  subscription_runner.within_state(:stopped) do
19
- subscription_runner.clear_chunk
19
+ subscription_runner.clear_events_repository
20
20
  subscription_runner.subscription.update(
21
21
  last_chunk_greatest_position: nil, current_position: data['position'], total_processed_events: 0
22
22
  )
@@ -15,15 +15,16 @@ module PgEventstore
15
15
  runners = runners.select(&:running?).select(&:time_to_feed?)
16
16
  return if runners.empty?
17
17
 
18
- safe_pos = subscription_service_queries.safe_global_position
19
- runners_query_options = runners.to_h do |runner|
20
- [runner.id, runner.next_chunk_query_opts.merge(to_position: safe_pos)]
21
- end
22
- grouped_events = subscription_queries.subscriptions_events(runners_query_options)
23
-
24
- runners.each do |runner|
25
- runner.feed(grouped_events[runner.id]) if grouped_events[runner.id]
18
+ feed_strategies_collection = SubscriptionFeedStrategy::Collection.create(
19
+ runners,
20
+ connection,
21
+ QueryStrategy::Async.new(connection)
22
+ )
23
+ query_runner = AsyncRunner.new
24
+ feed_strategies_collection.each do |strategy|
25
+ query_runner.async { strategy.feed }
26
26
  end
27
+ query_runner.run
27
28
  end
28
29
 
29
30
  private
@@ -32,15 +33,5 @@ module PgEventstore
32
33
  def connection
33
34
  PgEventstore.connection(@config_name)
34
35
  end
35
-
36
- # @return [PgEventstore::SubscriptionQueries]
37
- def subscription_queries
38
- SubscriptionQueries.new(connection)
39
- end
40
-
41
- # @return [PgEventstore::SubscriptionServiceQueries]
42
- def subscription_service_queries
43
- SubscriptionServiceQueries.new(connection)
44
- end
45
36
  end
46
37
  end
@@ -56,18 +56,6 @@ module PgEventstore
56
56
  @runners.map(&:subscription)
57
57
  end
58
58
 
59
- # Sets the force_lock flag to true. If set - all related Subscriptions will ignore their lock state and will be
60
- # locked by the new SubscriptionsSet.
61
- # @return [void]
62
- def force_lock!
63
- message = <<~TEXT
64
- Usage of #force_lock! is deprecated and will be removed in v2. Please pass :force_lock keyword argument when \
65
- initializing SubscriptionsManager. Example: PgEventstore.subscriptions_manager(force_lock: true)
66
- TEXT
67
- Utils.deprecation_warning(message)
68
- @force_lock = true
69
- end
70
-
71
59
  # @return [Boolean]
72
60
  def force_locked?
73
61
  @force_lock
@@ -6,18 +6,22 @@ require_relative 'basic_runner'
6
6
  require_relative 'runner_recovery_strategy'
7
7
  require_relative 'runner_recovery_strategies'
8
8
  require_relative 'subscription'
9
- require_relative 'synchronized_array'
9
+ require_relative 'events_processor_consumer'
10
10
  require_relative 'events_processor'
11
11
  require_relative 'subscription_handler_performance'
12
12
  require_relative 'subscription_runner'
13
13
  require_relative 'subscriptions_set'
14
+ require_relative 'subscription_feed_strategy'
14
15
  require_relative 'subscription_runners_feeder'
15
16
  require_relative 'subscriptions_set_lifecycle'
16
17
  require_relative 'subscriptions_lifecycle'
17
18
  require_relative 'callback_handlers/subscription_feeder_handlers'
18
19
  require_relative 'callback_handlers/subscription_runner_handlers'
19
20
  require_relative 'callback_handlers/events_processor_handlers'
21
+ require_relative 'callback_handlers/events_subscription_position_worker_handlers'
20
22
  require_relative 'callback_handlers/commands_handler_handlers'
23
+ require_relative 'commands_handler'
24
+ require_relative 'events_subscription_position_worker'
21
25
  require_relative 'subscription_feeder'
22
26
  require_relative 'extensions/command_class_lookup_extension'
23
27
  require_relative 'extensions/base_command_extension'
@@ -25,10 +29,11 @@ require_relative 'subscription_feeder_commands'
25
29
  require_relative 'subscription_runner_commands'
26
30
  require_relative 'queries/subscription_command_queries'
27
31
  require_relative 'queries/subscription_queries'
28
- require_relative 'queries/subscription_service_queries'
32
+ require_relative 'queries/event_subscription_position_queries'
29
33
  require_relative 'queries/subscriptions_set_command_queries'
30
34
  require_relative 'queries/subscriptions_set_queries'
31
- require_relative 'commands_handler'
35
+ require_relative 'replica_subscription_handler'
36
+ require_relative 'replica_subscription_runner'
32
37
 
33
38
  module PgEventstore
34
39
  # The public Subscriptions API, available to the user.
@@ -41,7 +46,6 @@ module PgEventstore
41
46
  private :config
42
47
 
43
48
  def_delegators :@subscription_feeder, :stop, :running?
44
- def_delegators :@subscriptions_lifecycle, :force_lock!
45
49
 
46
50
  # @param config [PgEventstore::Config]
47
51
  # @param set_name [String]
@@ -71,8 +75,8 @@ module PgEventstore
71
75
 
72
76
  # @param subscription_name [String] subscription's name
73
77
  # @param handler [#call] subscription's handler
74
- # @param options [Hash] request options
75
- # @option options [Integer, Symbol] :from_position a starting subscription position
78
+ # @param options [Hash] subscription options
79
+ # @option options [Integer] :from_position a starting subscription position
76
80
  # @option options [Boolean] :resolve_link_tos When using projections to create new events you
77
81
  # can set whether the generated events are pointers to existing events. Setting this option to true tells
78
82
  # PgEventstore to return the original event instead a link event.
@@ -91,6 +95,7 @@ module PgEventstore
91
95
  # notification about failed subscription.
92
96
  # @param graceful_shutdown_timeout [integer, Float] the number of seconds to wait until force-shutdown the
93
97
  # subscription during the stop process
98
+ # @param in_batches [Boolean] whether a batch of events should be yielded instead a single event
94
99
  # @return [void]
95
100
  def subscribe(subscription_name, handler:, options: {}, middlewares: nil,
96
101
  pull_interval: config.subscription_pull_interval,
@@ -98,16 +103,18 @@ module PgEventstore
98
103
  retries_interval: config.subscription_retries_interval,
99
104
  restart_terminator: config.subscription_restart_terminator,
100
105
  failed_subscription_notifier: config.failed_subscription_notifier,
101
- graceful_shutdown_timeout: config.subscription_graceful_shutdown_timeout)
106
+ graceful_shutdown_timeout: config.subscription_graceful_shutdown_timeout,
107
+ in_batches: false)
102
108
  subscription = Subscription.using_connection(config.name).new(
103
109
  set: @set_name, name: subscription_name, options:, chunk_query_interval: pull_interval,
104
110
  max_restarts_number: max_retries, time_between_restarts: retries_interval
105
111
  )
112
+ consumer_class = EventsProcessorConsumer.consumer_class(in_batches)
106
113
  runner = SubscriptionRunner.new(
107
114
  stats: SubscriptionHandlerPerformance.new,
108
115
  events_processor: EventsProcessor.new(
109
- create_raw_event_handler(middlewares, handler),
110
116
  graceful_shutdown_timeout:,
117
+ consumer: consumer_class.create_consumer(handler, deserializer(middlewares)),
111
118
  recovery_strategies: recovery_strategies(subscription, restart_terminator, failed_subscription_notifier)
112
119
  ),
113
120
  subscription:
@@ -117,6 +124,63 @@ module PgEventstore
117
124
  true
118
125
  end
119
126
 
127
+ # @param subscription_name [String] subscription's name. For example, you can name it after the target database:
128
+ # "Target: my_eventstore_replica1"
129
+ # @param replica_config_name [Symbol] the destination replica database config to replicate events into. You have to
130
+ # have it preconfigured with PgEventstore.configure(). Example:
131
+ # PgEventstore.configure(name: :my_eventstore_replica1) do |config|
132
+ # config.pg_uri = 'postgresql://postgres:postgres@localhost:5432/my_eventstore_replica1'
133
+ # end
134
+ # Refer to the docs/configuration.md for more info
135
+ # @param options [Hash] subscription options
136
+ # @option options [Integer] :from_position a starting subscription position
137
+ # @option options [Hash] :filter provide it to filter events. It works the same way as a :filter option of
138
+ # {PgEventstore::Client#read} method. Use this option when you want to replicate certain set of events.
139
+ # @param max_events_to_replicate [Integer] set the upper limit of how many events the handler can copy per turn
140
+ # @param pull_interval [Integer, Float] an interval in seconds to determine how often to query new events of the
141
+ # given subscription.
142
+ # @param max_retries [Integer] max number of retries of failed Subscription
143
+ # @param retries_interval [Integer, Float] a delay between retries of failed Subscription
144
+ # @param restart_terminator [#call, nil] a callable object which is invoked with PgEventstore::Subscription instance
145
+ # to determine whether restarts should be stopped(true - stops restarts, false - continues restarts)
146
+ # @param failed_subscription_notifier [#call, nil] a callable object which is invoked with
147
+ # PgEventstore::Subscription instance and error instance after the related subscription died due to error and no
148
+ # longer can be automatically restarted due to max retries number reached. You can use this hook to send a
149
+ # notification about failed subscription.
150
+ # @param graceful_shutdown_timeout [Integer, Float] the number of seconds to wait until force-shutdown the
151
+ # subscription during the stop process
152
+ # @return [void]
153
+ def create_replication(subscription_name,
154
+ replica_config_name,
155
+ options: {},
156
+ max_events_to_replicate: config.max_events_to_replicate,
157
+ pull_interval: config.subscription_pull_interval,
158
+ max_retries: config.subscription_max_retries,
159
+ retries_interval: config.subscription_retries_interval,
160
+ restart_terminator: config.subscription_restart_terminator,
161
+ failed_subscription_notifier: config.failed_subscription_notifier,
162
+ graceful_shutdown_timeout: config.subscription_graceful_shutdown_timeout)
163
+ Utils.assert_node_role!(config, [Config::NodeRole::PRIMARY])
164
+ subscription = Subscription.using_connection(config.name).new(
165
+ set: @set_name, name: subscription_name, options:, chunk_query_interval: pull_interval,
166
+ max_restarts_number: max_retries, time_between_restarts: retries_interval
167
+ )
168
+ runner = ReplicaSubscriptionRunner.new(
169
+ stats: SubscriptionHandlerPerformance.new,
170
+ events_processor: EventsProcessor.new(
171
+ graceful_shutdown_timeout:,
172
+ consumer: EventsProcessorConsumer::Replica.create_consumer(config_name, replica_config_name),
173
+ recovery_strategies: recovery_strategies(subscription, restart_terminator, failed_subscription_notifier)
174
+ ),
175
+ subscription:,
176
+ max_events_per_chunk: max_events_to_replicate,
177
+ initial_events_per_chunk: max_events_to_replicate
178
+ )
179
+
180
+ @subscriptions_lifecycle.runners.push(runner)
181
+ true
182
+ end
183
+
120
184
  # @return [Array<PgEventstore::Subscription>]
121
185
  def subscriptions
122
186
  @subscriptions_lifecycle.subscriptions.map(&:dup)
@@ -157,12 +221,8 @@ module PgEventstore
157
221
  PgEventstore::CLI.callbacks.run_callbacks(:start_manager, self, &)
158
222
  end
159
223
 
160
- # @param middlewares [Array<Symbol>, nil]
161
- # @param handler [#call]
162
- # @return [Proc]
163
- def create_raw_event_handler(middlewares, handler)
164
- deserializer = EventDeserializer.new(select_middlewares(middlewares), config.event_class_resolver)
165
- ->(raw_event) { handler.call(deserializer.deserialize(raw_event)) }
224
+ def deserializer(middlewares)
225
+ EventDeserializer.new(select_middlewares(middlewares), config.event_class_resolver)
166
226
  end
167
227
 
168
228
  # @param middlewares [Array, nil]
@@ -13,6 +13,9 @@ module PgEventstore
13
13
  alias old_clear clear
14
14
  alias old_size size
15
15
  alias old_empty? empty?
16
+ alias old_slice slice
17
+ alias old_slice! slice!
18
+ alias old_at at
16
19
 
17
20
  def shift(...)
18
21
  synchronize { old_shift(...) }
@@ -37,5 +40,17 @@ module PgEventstore
37
40
  def empty?(...)
38
41
  synchronize { old_empty?(...) }
39
42
  end
43
+
44
+ def slice(...)
45
+ synchronize { old_slice(...) }
46
+ end
47
+
48
+ def slice!(...)
49
+ synchronize { old_slice!(...) }
50
+ end
51
+
52
+ def at(...)
53
+ synchronize { old_at(...) }
54
+ end
40
55
  end
41
56
  end
@@ -46,7 +46,7 @@ namespace :pg_eventstore do
46
46
  end
47
47
 
48
48
  task :migrate do
49
- migration_files_root = "#{Gem::Specification.find_by_name('pg_eventstore').gem_dir}/db/migrations"
49
+ migration_files_root = File.join(Gem.loaded_specs.fetch('pg_eventstore').gem_dir, 'db/migrations')
50
50
 
51
51
  PgEventstore.connection(:_eventstore_db_connection).with do |conn|
52
52
  conn.exec('CREATE TABLE IF NOT EXISTS migrations (number int NOT NULL)')
@@ -59,7 +59,7 @@ namespace :pg_eventstore do
59
59
  next if latest_migration >= number
60
60
 
61
61
  if File.extname(f_name) == '.rb'
62
- load f_name
62
+ load(f_name, true)
63
63
  else
64
64
  conn.exec(File.read(f_name))
65
65
  end
@@ -132,6 +132,37 @@ module PgEventstore
132
132
  yield
133
133
  Process.clock_gettime(Process::CLOCK_MONOTONIC) - start_time
134
134
  end
135
+
136
+ # @param truthy [boolish]
137
+ # @param message [String, nil]
138
+ # @raise ArgumentError
139
+ def assert!(truthy, message = nil)
140
+ raise ArgumentError, message unless truthy
141
+ end
142
+
143
+ # @param obj
144
+ # @raise NotImplementedError
145
+ def missing_implementation!(obj)
146
+ raise NotImplementedError, obj.inspect
147
+ end
148
+
149
+ # @param config [PgEventstore::Config]
150
+ # @param expected_roles [Array<Symbol>]
151
+ # @return [void]
152
+ def assert_node_role!(config, expected_roles)
153
+ return if expected_roles.include?(config.eventstore_role)
154
+
155
+ raise "You can't perform this operation on #{config.eventstore_role.inspect} node!"
156
+ end
157
+
158
+ # Takes a collection of partition ids, the number of partitions per call and determines the position in the
159
+ # partition_ids at which we have max_partitions_to_resolve_per_call unique partitions
160
+ # @param partition_ids [Array<Integer>]
161
+ # @param max_partitions_to_resolve_per_call [Integer]
162
+ # @return [Range]
163
+ def range_to_slice(partition_ids, max_partitions_to_resolve_per_call)
164
+ # This is stub, used for indexing
165
+ end
135
166
  end
136
167
  end
137
168
  end
@@ -2,5 +2,5 @@
2
2
 
3
3
  module PgEventstore
4
4
  # @return [String]
5
- VERSION = '2.0.0'
5
+ VERSION = '3.0.0'
6
6
  end