pg_eventstore 1.13.4 → 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 (319) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop.yml +11 -2
  3. data/CHANGELOG.md +195 -16
  4. data/README.md +33 -10
  5. data/db/migrations/10_setup_pg_cron.rb +1 -0
  6. data/db/migrations/11_add_events_link_global_position.sql +1 -0
  7. data/db/migrations/12_migrate_legacy_links.rb +83 -0
  8. data/db/migrations/13_remove_events_link_id.sql +6 -0
  9. data/db/migrations/14_remove_ids_events_id_index.sql +1 -0
  10. data/db/migrations/15_create_streams_global_index.sql +17 -0
  11. data/db/migrations/16_populate_streams_global_index.rb +150 -0
  12. data/db/migrations/17_create_events_global_index.sql +62 -0
  13. data/db/migrations/18_populate_events_global_index.rb +124 -0
  14. data/db/migrations/19_populate_events_global_index_p2.rb +25 -0
  15. data/db/migrations/20_migrate_subscriptions_current_position.sql +19 -0
  16. data/db/migrations/21_create_partitions_stats.sql +2 -0
  17. data/db/migrations/22_drop_streams_sql_view.sql +2 -0
  18. data/db/migrations/23_adjust_partitions_indexes.sql +5 -0
  19. data/db/migrations/24_drop_legacy_events_indexes.sql +3 -0
  20. data/db/migrations/25_add_parent_partitions_info_to_partitions.sql +16 -0
  21. data/db/migrations/26_change_events_stream_revision_type.rb +35 -0
  22. data/db/migrations/27_drop_events_horizon.sql +3 -0
  23. data/db/migrations/28_create_maintenance_tasks.sql +8 -0
  24. data/db/migrations/29_create_event_markers.sql +35 -0
  25. data/db/migrations/30_improve_partitions_search_in_admin_ui.rb +24 -0
  26. data/db/migrations/31_drop_events_id_default_value.sql +1 -0
  27. data/db/migrations/32_create_parittions_triggers.sql +101 -0
  28. data/db/migrations/9_create_events_horizon.sql +21 -0
  29. data/docs/AGENTS.fragment.md +696 -0
  30. data/docs/admin_ui.md +3 -1
  31. data/docs/appending_events.md +110 -49
  32. data/docs/configuration.md +69 -36
  33. data/docs/event_tracing.md +55 -0
  34. data/docs/events_and_streams.md +54 -30
  35. data/docs/how_it_works.md +57 -16
  36. data/docs/linking_events.md +2 -1
  37. data/docs/maintenance.md +14 -5
  38. data/docs/multiple_commands.md +30 -6
  39. data/docs/reading_events.md +208 -43
  40. data/docs/reading_streams.md +50 -0
  41. data/docs/replication.md +99 -0
  42. data/docs/subscriptions.md +165 -35
  43. data/docs/writing_middleware.md +25 -8
  44. data/ext/pg_eventstore_ext/extconf.rb +5 -0
  45. data/ext/pg_eventstore_ext/pg_eventstore_ext.c +74 -0
  46. data/lib/pg_eventstore/async_runner.rb +63 -0
  47. data/lib/pg_eventstore/basic_config.rb +15 -0
  48. data/lib/pg_eventstore/callbacks.rb +7 -5
  49. data/lib/pg_eventstore/chunks/chunk.rb +31 -0
  50. data/lib/pg_eventstore/chunks/read_api_events_index_chunk.rb +83 -0
  51. data/lib/pg_eventstore/chunks/replica_events_index_chunk.rb +35 -0
  52. data/lib/pg_eventstore/chunks/repository.rb +73 -0
  53. data/lib/pg_eventstore/chunks/subscription_checkpoint_chunk.rb +48 -0
  54. data/lib/pg_eventstore/chunks/subscription_events_index_chunk.rb +99 -0
  55. data/lib/pg_eventstore/chunks.rb +14 -0
  56. data/lib/pg_eventstore/cli/try_to_delete_subscriptions_set.rb +2 -2
  57. data/lib/pg_eventstore/client.rb +167 -52
  58. data/lib/pg_eventstore/commands/append.rb +62 -43
  59. data/lib/pg_eventstore/commands/delete_event.rb +7 -8
  60. data/lib/pg_eventstore/commands/delete_stream.rb +3 -3
  61. data/lib/pg_eventstore/commands/event_modifiers/prepare_link_event.rb +11 -6
  62. data/lib/pg_eventstore/commands/event_modifiers/prepare_regular_event.rb +12 -7
  63. data/lib/pg_eventstore/commands/link_to.rb +9 -9
  64. data/lib/pg_eventstore/commands/multiple.rb +2 -2
  65. data/lib/pg_eventstore/commands/read.rb +23 -5
  66. data/lib/pg_eventstore/commands/read_grouped.rb +46 -0
  67. data/lib/pg_eventstore/commands/read_streams.rb +18 -0
  68. data/lib/pg_eventstore/commands/read_streams_paginated.rb +56 -0
  69. data/lib/pg_eventstore/commands/regular_stream_read_paginated.rb +4 -4
  70. data/lib/pg_eventstore/commands/revision_check/current_revision.rb +51 -0
  71. data/lib/pg_eventstore/commands/revision_check/event_type_revisions_comparison.rb +46 -0
  72. data/lib/pg_eventstore/commands/revision_check/expected_revision.rb +135 -0
  73. data/lib/pg_eventstore/commands/revision_check/stream_revision_check.rb +98 -0
  74. data/lib/pg_eventstore/commands/revision_check/stream_revision_comparison.rb +36 -0
  75. data/lib/pg_eventstore/commands/stream_revision.rb +14 -0
  76. data/lib/pg_eventstore/commands/system_stream_read_paginated.rb +4 -4
  77. data/lib/pg_eventstore/commands.rb +4 -2
  78. data/lib/pg_eventstore/config.rb +30 -9
  79. data/lib/pg_eventstore/connection.rb +22 -37
  80. data/lib/pg_eventstore/errors.rb +137 -11
  81. data/lib/pg_eventstore/event.rb +39 -7
  82. data/lib/pg_eventstore/event_deserializer.rb +5 -4
  83. data/lib/pg_eventstore/event_global_index.rb +118 -0
  84. data/lib/pg_eventstore/event_marker.rb +16 -0
  85. data/lib/pg_eventstore/event_marker_index.rb +25 -0
  86. data/lib/pg_eventstore/event_serializer.rb +6 -0
  87. data/lib/pg_eventstore/extensions/acts_as_configurable.rb +88 -0
  88. data/lib/pg_eventstore/extensions/options_defaults.rb +25 -0
  89. data/lib/pg_eventstore/extensions/options_extension.rb +42 -13
  90. data/lib/pg_eventstore/feature_marker.rb +18 -0
  91. data/lib/pg_eventstore/maintenance.rb +11 -6
  92. data/lib/pg_eventstore/middleware/event_tracing.rb +53 -0
  93. data/lib/pg_eventstore/partition.rb +6 -0
  94. data/lib/pg_eventstore/pg_connection.rb +70 -14
  95. data/lib/pg_eventstore/queries/event_marker_queries.rb +74 -0
  96. data/lib/pg_eventstore/queries/event_queries.rb +9 -95
  97. data/lib/pg_eventstore/queries/events_global_index_queries.rb +131 -0
  98. data/lib/pg_eventstore/queries/index_filtering_queries.rb +179 -0
  99. data/lib/pg_eventstore/queries/links_resolver.rb +10 -7
  100. data/lib/pg_eventstore/queries/maintenance_queries.rb +159 -42
  101. data/lib/pg_eventstore/queries/partition_queries.rb +46 -104
  102. data/lib/pg_eventstore/queries/replica_queries.rb +110 -0
  103. data/lib/pg_eventstore/queries/streams_global_index_queries.rb +163 -0
  104. data/lib/pg_eventstore/queries/transaction_queries.rb +58 -10
  105. data/lib/pg_eventstore/queries.rb +29 -1
  106. data/lib/pg_eventstore/query_builders/basic_filtering.rb +38 -5
  107. data/lib/pg_eventstore/query_builders/event_markers_filtering.rb +47 -0
  108. data/lib/pg_eventstore/query_builders/event_markers_index_filtering.rb +275 -0
  109. data/lib/pg_eventstore/query_builders/event_subscription_positions_filtering.rb +37 -0
  110. data/lib/pg_eventstore/query_builders/events_filtering.rb +15 -164
  111. data/lib/pg_eventstore/query_builders/events_global_index_filtering.rb +227 -0
  112. data/lib/pg_eventstore/query_builders/filters/collection.rb +324 -0
  113. data/lib/pg_eventstore/query_builders/filters/event_type_filter.rb +37 -0
  114. data/lib/pg_eventstore/query_builders/filters/filter_row.rb +54 -0
  115. data/lib/pg_eventstore/query_builders/filters/marker_filter.rb +20 -0
  116. data/lib/pg_eventstore/query_builders/filters/marker_filter_row.rb +49 -0
  117. data/lib/pg_eventstore/query_builders/filters/stream_filter.rb +48 -0
  118. data/lib/pg_eventstore/query_builders/index_based_events_filtering.rb +260 -0
  119. data/lib/pg_eventstore/query_builders/partitions_filtering.rb +175 -51
  120. data/lib/pg_eventstore/query_builders/read_cursor/stream_cursor.rb +122 -0
  121. data/lib/pg_eventstore/query_builders/streams_global_index_filtering.rb +83 -0
  122. data/lib/pg_eventstore/query_builders/subscription_events_filtering.rb +79 -0
  123. data/lib/pg_eventstore/query_strategy/async.rb +64 -0
  124. data/lib/pg_eventstore/query_strategy/foreground.rb +25 -0
  125. data/lib/pg_eventstore/query_strategy.rb +19 -0
  126. data/lib/pg_eventstore/raw_event.rb +46 -0
  127. data/lib/pg_eventstore/rspec/test_helpers.rb +21 -8
  128. data/lib/pg_eventstore/sql_builder.rb +87 -8
  129. data/lib/pg_eventstore/stream.rb +14 -17
  130. data/lib/pg_eventstore/stream_global_index.rb +28 -0
  131. data/lib/pg_eventstore/subscriptions/basic_runner.rb +4 -4
  132. data/lib/pg_eventstore/subscriptions/callback_handlers/events_processor_handlers.rb +5 -17
  133. data/lib/pg_eventstore/subscriptions/callback_handlers/events_subscription_position_worker_handlers.rb +36 -0
  134. data/lib/pg_eventstore/subscriptions/callback_handlers/subscription_feeder_handlers.rb +13 -1
  135. data/lib/pg_eventstore/subscriptions/callback_handlers/subscription_runner_handlers.rb +19 -14
  136. data/lib/pg_eventstore/subscriptions/events_processor.rb +21 -19
  137. data/lib/pg_eventstore/subscriptions/events_processor_consumer/multiple.rb +63 -0
  138. data/lib/pg_eventstore/subscriptions/events_processor_consumer/replica.rb +68 -0
  139. data/lib/pg_eventstore/subscriptions/events_processor_consumer/single.rb +62 -0
  140. data/lib/pg_eventstore/subscriptions/events_processor_consumer.rb +44 -0
  141. data/lib/pg_eventstore/subscriptions/events_subscription_position_worker.rb +68 -0
  142. data/lib/pg_eventstore/subscriptions/queries/event_subscription_position_queries.rb +177 -0
  143. data/lib/pg_eventstore/subscriptions/queries/subscription_command_queries.rb +5 -5
  144. data/lib/pg_eventstore/subscriptions/queries/subscription_queries.rb +80 -56
  145. data/lib/pg_eventstore/subscriptions/queries/subscriptions_set_command_queries.rb +2 -2
  146. data/lib/pg_eventstore/subscriptions/queries/subscriptions_set_queries.rb +1 -1
  147. data/lib/pg_eventstore/subscriptions/replica_subscription_handler.rb +140 -0
  148. data/lib/pg_eventstore/subscriptions/replica_subscription_runner.rb +9 -0
  149. data/lib/pg_eventstore/subscriptions/subscription.rb +9 -7
  150. data/lib/pg_eventstore/subscriptions/subscription_feed_strategies/collection.rb +36 -0
  151. data/lib/pg_eventstore/subscriptions/subscription_feed_strategies/index_read_strategy.rb +82 -0
  152. data/lib/pg_eventstore/subscriptions/subscription_feed_strategies/replication_strategy.rb +75 -0
  153. data/lib/pg_eventstore/subscriptions/subscription_feed_strategy.rb +31 -0
  154. data/lib/pg_eventstore/subscriptions/subscription_feeder.rb +26 -2
  155. data/lib/pg_eventstore/subscriptions/subscription_handler_performance.rb +5 -5
  156. data/lib/pg_eventstore/subscriptions/subscription_runner.rb +20 -22
  157. data/lib/pg_eventstore/subscriptions/subscription_runner_commands/reset_position.rb +1 -1
  158. data/lib/pg_eventstore/subscriptions/subscription_runners_feeder.rb +10 -11
  159. data/lib/pg_eventstore/subscriptions/subscriptions_lifecycle.rb +0 -12
  160. data/lib/pg_eventstore/subscriptions/subscriptions_manager.rb +84 -29
  161. data/lib/pg_eventstore/{subscriptions/synchronized_array.rb → synchronized_array.rb} +15 -0
  162. data/lib/pg_eventstore/tasks/setup.rake +32 -33
  163. data/lib/pg_eventstore/utils.rb +39 -0
  164. data/lib/pg_eventstore/version.rb +1 -1
  165. data/lib/pg_eventstore/web/application.rb +104 -20
  166. data/lib/pg_eventstore/web/paginator/base_collection.rb +5 -1
  167. data/lib/pg_eventstore/web/paginator/event_types_collection.rb +14 -4
  168. data/lib/pg_eventstore/web/paginator/events_collection.rb +29 -33
  169. data/lib/pg_eventstore/web/paginator/helpers.rb +19 -12
  170. data/lib/pg_eventstore/web/paginator/markers_collection.rb +48 -0
  171. data/lib/pg_eventstore/web/paginator/stream_contexts_collection.rb +13 -2
  172. data/lib/pg_eventstore/web/paginator/stream_ids_collection.rb +21 -11
  173. data/lib/pg_eventstore/web/paginator/stream_names_collection.rb +18 -4
  174. data/lib/pg_eventstore/web/paginator/streams_collection.rb +95 -0
  175. data/lib/pg_eventstore/web/public/javascripts/pg_eventstore.js +49 -22
  176. data/lib/pg_eventstore/web/subscriptions/helpers.rb +2 -2
  177. data/lib/pg_eventstore/web/subscriptions/set_collection.rb +1 -1
  178. data/lib/pg_eventstore/web/subscriptions/subscriptions.rb +1 -1
  179. data/lib/pg_eventstore/web/subscriptions/with_state/set_collection.rb +1 -1
  180. data/lib/pg_eventstore/web/subscriptions/with_state/subscriptions.rb +1 -1
  181. data/lib/pg_eventstore/web/views/home/dashboard.erb +11 -9
  182. data/lib/pg_eventstore/web/views/home/partials/event_filter.erb +18 -5
  183. data/lib/pg_eventstore/web/views/home/partials/events.erb +38 -1
  184. data/lib/pg_eventstore/web/views/home/partials/markers_filter.erb +18 -0
  185. data/lib/pg_eventstore/web/views/layouts/application.erb +6 -0
  186. data/lib/pg_eventstore/web/views/streams/index.erb +110 -0
  187. data/lib/pg_eventstore/web/views/streams/partials/streams.erb +11 -0
  188. data/lib/pg_eventstore/web/views/subscriptions/index.erb +4 -1
  189. data/lib/pg_eventstore/web.rb +2 -0
  190. data/lib/pg_eventstore.rb +26 -63
  191. data/pg_eventstore.gemspec +6 -4
  192. data/sig/interfaces/_raw_events_handler.rbs +3 -0
  193. data/sig/interfaces/subscription_handler.rbs +1 -1
  194. data/sig/pg/result.rbs +9 -0
  195. data/sig/pg_eventstore/async_runner.rbs +13 -0
  196. data/sig/pg_eventstore/basic_config.rbs +9 -0
  197. data/sig/pg_eventstore/chunks/chunk.rbs +13 -0
  198. data/sig/pg_eventstore/chunks/read_api_events_index_chunk.rbs +30 -0
  199. data/sig/pg_eventstore/chunks/replica_events_index_chunk.rbs +11 -0
  200. data/sig/pg_eventstore/chunks/repository.rbs +22 -0
  201. data/sig/pg_eventstore/chunks/subscription_checkpoint_chunk.rbs +18 -0
  202. data/sig/pg_eventstore/chunks/subscription_events_index_chunk.rbs +37 -0
  203. data/sig/pg_eventstore/client.rbs +41 -43
  204. data/sig/pg_eventstore/commands/append.rbs +11 -25
  205. data/sig/pg_eventstore/commands/event_modifiers/prepare_link_event.rbs +9 -12
  206. data/sig/pg_eventstore/commands/event_modifiers/prepare_regular_event.rbs +5 -4
  207. data/sig/pg_eventstore/commands/link_to.rbs +6 -11
  208. data/sig/pg_eventstore/commands/multiple.rbs +1 -1
  209. data/sig/pg_eventstore/commands/read.rbs +2 -5
  210. data/sig/pg_eventstore/commands/read_grouped.rbs +7 -0
  211. data/sig/pg_eventstore/commands/read_streams.rbs +7 -0
  212. data/sig/pg_eventstore/commands/read_streams_paginated.rbs +16 -0
  213. data/sig/pg_eventstore/commands/regular_stream_read_paginated.rbs +9 -17
  214. data/sig/pg_eventstore/commands/revision_check/current_revision.rbs +25 -0
  215. data/sig/pg_eventstore/commands/revision_check/event_type_revisions_comparison.rbs +14 -0
  216. data/sig/pg_eventstore/commands/revision_check/expected_revision.rbs +67 -0
  217. data/sig/pg_eventstore/commands/revision_check/stream_revision_check.rbs +20 -0
  218. data/sig/pg_eventstore/commands/revision_check/stream_revision_comparison.rbs +9 -0
  219. data/sig/pg_eventstore/commands/stream_revision.rbs +7 -0
  220. data/sig/pg_eventstore/commands/system_stream_read_paginated.rbs +9 -14
  221. data/sig/pg_eventstore/config.rbs +15 -6
  222. data/sig/pg_eventstore/connection.rbs +11 -18
  223. data/sig/pg_eventstore/errors.rbs +64 -34
  224. data/sig/pg_eventstore/event.rbs +20 -6
  225. data/sig/pg_eventstore/event_deserializer.rbs +5 -10
  226. data/sig/pg_eventstore/event_global_index.rbs +60 -0
  227. data/sig/pg_eventstore/event_marker.rbs +9 -0
  228. data/sig/pg_eventstore/event_marker_index.rbs +12 -0
  229. data/sig/pg_eventstore/extensions/acts_as_configurable.rbs +29 -0
  230. data/sig/pg_eventstore/extensions/options_defaults.rbs +7 -0
  231. data/sig/pg_eventstore/extensions/options_extension.rbs +9 -1
  232. data/sig/pg_eventstore/feature_marker.rbs +10 -0
  233. data/sig/pg_eventstore/maintenance.rbs +12 -8
  234. data/sig/pg_eventstore/middleware/event_trace.rbs +14 -0
  235. data/sig/pg_eventstore/partition.rbs +2 -4
  236. data/sig/pg_eventstore/pg_connection.rbs +8 -0
  237. data/sig/pg_eventstore/queries/event_marker_queries.rbs +21 -0
  238. data/sig/pg_eventstore/queries/event_queries.rbs +6 -38
  239. data/sig/pg_eventstore/queries/events_global_index_queries.rbs +37 -0
  240. data/sig/pg_eventstore/queries/index_filtering_queries.rbs +50 -0
  241. data/sig/pg_eventstore/queries/links_resolver.rbs +7 -11
  242. data/sig/pg_eventstore/queries/maintenance_queries.rbs +12 -9
  243. data/sig/pg_eventstore/queries/partition_queries.rbs +32 -67
  244. data/sig/pg_eventstore/queries/replica_queries.rbs +31 -0
  245. data/sig/pg_eventstore/queries/streams_global_index_queries.rbs +39 -0
  246. data/sig/pg_eventstore/queries/transaction_queries.rbs +4 -2
  247. data/sig/pg_eventstore/queries.rbs +11 -21
  248. data/sig/pg_eventstore/query_builders/basic_filtering.rbs +10 -3
  249. data/sig/pg_eventstore/query_builders/event_markers_filtering.rbs +17 -0
  250. data/sig/pg_eventstore/query_builders/event_markers_index_filtering.rbs +69 -0
  251. data/sig/pg_eventstore/query_builders/event_subscription_positions_filtering.rbs +15 -0
  252. data/sig/pg_eventstore/query_builders/events_filtering_query.rbs +9 -51
  253. data/sig/pg_eventstore/query_builders/events_global_index_filtering.rbs +68 -0
  254. data/sig/pg_eventstore/query_builders/filters/collection.rbs +84 -0
  255. data/sig/pg_eventstore/query_builders/filters/event_type_filter.rbs +19 -0
  256. data/sig/pg_eventstore/query_builders/filters/filter_row.rbs +21 -0
  257. data/sig/pg_eventstore/query_builders/filters/marker_filter.rbs +13 -0
  258. data/sig/pg_eventstore/query_builders/filters/marker_filter_row.rbs +19 -0
  259. data/sig/pg_eventstore/query_builders/filters/stream_filter.rbs +24 -0
  260. data/sig/pg_eventstore/query_builders/index_based_events_filtering.rbs +60 -0
  261. data/sig/pg_eventstore/query_builders/partitions_filtering.rbs +29 -10
  262. data/sig/pg_eventstore/query_builders/read_cursor/stream_cursor.rbs +47 -0
  263. data/sig/pg_eventstore/query_builders/streams_global_index_filtering.rbs +27 -0
  264. data/sig/pg_eventstore/query_builders/subscription_events_filtering.rbs +26 -0
  265. data/sig/pg_eventstore/query_strategy/async.rbs +17 -0
  266. data/sig/pg_eventstore/query_strategy/foreground.rbs +11 -0
  267. data/sig/pg_eventstore/query_strategy.rbs +7 -0
  268. data/sig/pg_eventstore/raw_event.rbs +20 -0
  269. data/sig/pg_eventstore/sql_builder.rbs +32 -10
  270. data/sig/pg_eventstore/stream.rbs +10 -18
  271. data/sig/pg_eventstore/stream_global_index.rbs +14 -0
  272. data/sig/pg_eventstore/subscriptions/callback_handlers/events_processor_handlers.rbs +5 -4
  273. data/sig/pg_eventstore/subscriptions/callback_handlers/events_subscription_position_worker_handlers.rbs +9 -0
  274. data/sig/pg_eventstore/subscriptions/callback_handlers/subscription_feeder_handlers.rbs +17 -12
  275. data/sig/pg_eventstore/subscriptions/callback_handlers/subscription_runner_handlers.rbs +16 -8
  276. data/sig/pg_eventstore/subscriptions/event_subscription_position_queries.rbs +30 -0
  277. data/sig/pg_eventstore/subscriptions/events_processor.rbs +12 -5
  278. data/sig/pg_eventstore/subscriptions/events_processor_consumer/multiple.rbs +17 -0
  279. data/sig/pg_eventstore/subscriptions/events_processor_consumer/replica.rbs +17 -0
  280. data/sig/pg_eventstore/subscriptions/events_processor_consumer/single.rbs +17 -0
  281. data/sig/pg_eventstore/subscriptions/events_processor_consumer.rbs +14 -0
  282. data/sig/pg_eventstore/subscriptions/events_subscription_position_worker.rbs +28 -0
  283. data/sig/pg_eventstore/subscriptions/queries/subscription_queries.rbs +18 -50
  284. data/sig/pg_eventstore/subscriptions/replica_subscription_handler.rbs +33 -0
  285. data/sig/pg_eventstore/subscriptions/replica_subscription_runner.rbs +4 -0
  286. data/sig/pg_eventstore/subscriptions/subscription_feed_strategy/collection.rbs +14 -0
  287. data/sig/pg_eventstore/subscriptions/subscription_feed_strategy/index_read_strategy.rbs +23 -0
  288. data/sig/pg_eventstore/subscriptions/subscription_feed_strategy/replication_strategy.rbs +23 -0
  289. data/sig/pg_eventstore/subscriptions/subscription_feed_strategy.rbs +11 -0
  290. data/sig/pg_eventstore/subscriptions/subscription_feeder.rbs +13 -10
  291. data/sig/pg_eventstore/subscriptions/subscription_handler_performance.rbs +1 -1
  292. data/sig/pg_eventstore/subscriptions/subscription_runner.rbs +13 -5
  293. data/sig/pg_eventstore/subscriptions/subscription_runners_feeder.rbs +5 -5
  294. data/sig/pg_eventstore/subscriptions/subscriptions_lifecycle.rbs +4 -6
  295. data/sig/pg_eventstore/subscriptions/subscriptions_manager.rbs +29 -43
  296. data/sig/pg_eventstore/synchronized_array.rbs +4 -0
  297. data/sig/pg_eventstore/utils.rbs +18 -11
  298. data/sig/pg_eventstore/web/application.rbs +13 -3
  299. data/sig/pg_eventstore/web/paginator/base_collection.rbs +2 -0
  300. data/sig/pg_eventstore/web/paginator/event_types_collection.rbs +4 -0
  301. data/sig/pg_eventstore/web/paginator/events_collection.rbs +11 -11
  302. data/sig/pg_eventstore/web/paginator/helpers.rbs +6 -15
  303. data/sig/pg_eventstore/web/paginator/markers_collection.rbs +13 -0
  304. data/sig/pg_eventstore/web/paginator/stream_contexts_collection.rbs +4 -0
  305. data/sig/pg_eventstore/web/paginator/stream_names_collection.rbs +4 -0
  306. data/sig/pg_eventstore/web/paginator/streams_collection.rbs +30 -0
  307. data/sig/pg_eventstore.rbs +8 -26
  308. metadata +181 -21
  309. data/lib/pg_eventstore/commands/all_stream_read_grouped.rb +0 -69
  310. data/lib/pg_eventstore/commands/regular_stream_read_grouped.rb +0 -31
  311. data/lib/pg_eventstore/subscriptions/queries/service_queries.rb +0 -73
  312. data/lib/pg_eventstore/subscriptions/subscription_position_evaluation.rb +0 -195
  313. data/lib/pg_eventstore/web/views/home/partials/system_stream_filter.erb +0 -15
  314. data/sig/pg_eventstore/commands/all_stream_read_grouped.rbs +0 -16
  315. data/sig/pg_eventstore/commands/regular_stream_read_grouped.rbs +0 -8
  316. data/sig/pg_eventstore/subscriptions/queries/service_queries.rbs +0 -15
  317. data/sig/pg_eventstore/subscriptions/subscription_position_evaluation.rbs +0 -53
  318. data/sig/pg_eventstore/subscriptions/synchronized_array.rbs +0 -4
  319. /data/sig/interfaces/{_raw_event_handler.rbs → raw_event_handler.rbs} +0 -0
@@ -19,57 +19,46 @@ module PgEventstore
19
19
  # count instead because of the potential performance degradation.
20
20
  MAX_NUMBER_TO_COUNT = 10_000
21
21
 
22
- # @param config_name [Symbol]
23
- # @param starting_id [String, Integer, nil]
24
- # @param per_page [Integer]
25
- # @param order [Symbol] :asc or :desc
26
- # @param options [Hash] additional options to filter the collection
27
- # @param system_stream [String, nil] a name of system stream
28
- def initialize(config_name, starting_id:, per_page:, order:, options: {}, system_stream: nil)
29
- super(config_name, starting_id: starting_id, per_page: per_page, order: order, options: options)
30
- @stream = system_stream ? PgEventstore::Stream.system_stream(system_stream) : PgEventstore::Stream.all_stream
31
- end
32
-
33
22
  # @return [Array<PgEventstore::Event>]
34
23
  def collection
35
- @collection ||= PgEventstore.client(config_name).read(
36
- @stream,
37
- options: options.merge(from_position: starting_id, max_count: per_page, direction: order)
38
- )
24
+ _collection[0...per_page]
39
25
  end
40
26
 
41
27
  # @return [Integer, nil]
42
28
  def next_page_starting_id
43
29
  return unless collection.size == per_page
44
30
 
45
- from_position = event_global_position(collection.first)
46
- sql_builder = QueryBuilders::EventsFiltering.events_filtering(
47
- @stream,
48
- options.merge(from_position: from_position, max_count: 1, direction: order)
49
- ).to_sql_builder.unselect.select('global_position').offset(per_page)
50
- global_position(sql_builder)
31
+ event_global_position(_collection[per_page])
51
32
  end
52
33
 
53
34
  # @return [Integer, nil]
54
35
  def prev_page_starting_id
55
- from_position = event_global_position(collection.first) || starting_id
56
- sql_builder = QueryBuilders::EventsFiltering.events_filtering(
57
- @stream,
58
- options.merge(from_position: from_position, max_count: per_page, direction: order == :asc ? :desc : :asc)
59
- ).to_sql_builder.unselect.select('global_position').offset(1)
60
- sql, params = sql_builder.to_exec_params
61
- sql = "SELECT * FROM (#{sql}) #{Event::PRIMARY_TABLE_NAME} ORDER BY global_position #{order} LIMIT 1"
62
- connection.with do |conn|
63
- conn.exec_params(sql, params)
64
- end.to_a.dig(0, 'global_position')
36
+ starting_position = event_global_position(_collection.first) || starting_id
37
+ return unless starting_position
38
+
39
+ order = self.order == :asc ? :desc : :asc
40
+ starting_position = self.order == :asc ? starting_position - 1 : starting_position + 1
41
+
42
+ # Not ideal from the perspective of the amount of records we load here, but this is the only way to read from
43
+ # the db in the correct way. Direct usage of query builders may result in heavy, unoptimized queries.
44
+ options = self.options.merge(
45
+ from_position: starting_position, max_count: per_page, direction: order, resolve_link_tos: false
46
+ )
47
+ PgEventstore.client(config_name).read(
48
+ PgEventstore::Stream.all_stream,
49
+ options:,
50
+ middlewares: []
51
+ ).last&.global_position
65
52
  end
66
53
 
67
54
  # @return [Integer]
68
55
  def total_count
69
56
  @total_count ||=
70
57
  begin
71
- sql_builder = QueryBuilders::EventsFiltering.events_filtering(@stream, options).to_sql_builder
72
- sql_builder.remove_limit.remove_group.remove_order
58
+ filters_collection = QueryBuilders::Filters::Collection.from_options(options)
59
+ sql_builder = QueryBuilders::IndexBasedEventsFiltering.sql_builder_for_estimate_count(
60
+ filters_collection.collection
61
+ )
73
62
  count = estimate_count(sql_builder)
74
63
  return count if count > MAX_NUMBER_TO_COUNT
75
64
 
@@ -79,6 +68,13 @@ module PgEventstore
79
68
 
80
69
  private
81
70
 
71
+ def _collection
72
+ @_collection ||= PgEventstore.client(config_name).read(
73
+ PgEventstore::Stream.all_stream,
74
+ options: options.merge(from_position: starting_id, max_count: per_page + 1, direction: order)
75
+ )
76
+ end
77
+
82
78
  # @param event [PgEventstore::Event, nil]
83
79
  # @return [Integer, nil]
84
80
  def event_global_position(event)
@@ -41,13 +41,13 @@ module PgEventstore
41
41
  # @param per_page [String] string representation of items per page. E.g. "10", "20", etc.
42
42
  # @return [String]
43
43
  def per_page_url(per_page)
44
- build_path(params.merge(per_page: per_page))
44
+ build_path(params.merge(per_page:))
45
45
  end
46
46
 
47
47
  # @param order [String] "asc"/"desc"
48
48
  # @return [String]
49
49
  def sort_url(order)
50
- build_path(params.merge(order: order))
50
+ build_path(params.merge(order:))
51
51
  end
52
52
 
53
53
  def resolve_link_tos_url(should_resolve)
@@ -80,24 +80,31 @@ module PgEventstore
80
80
  parts.join(delimiter)
81
81
  end
82
82
 
83
- # @param event [PgEventstore::Event]
83
+ # @param stream [PgEventstore::Stream]
84
84
  # @return [String]
85
- def stream_path(event)
85
+ def stream_path(stream)
86
86
  build_path(
87
87
  {
88
88
  filter: {
89
89
  streams: [
90
90
  {
91
- context: escape_empty_string(event.stream.context),
92
- stream_name: escape_empty_string(event.stream.stream_name),
93
- stream_id: escape_empty_string(event.stream.stream_id),
91
+ context: escape_empty_string(stream.context),
92
+ stream_name: escape_empty_string(stream.stream_name),
93
+ stream_id: escape_empty_string(stream.stream_id),
94
94
  },
95
95
  ],
96
96
  },
97
- }
97
+ },
98
+ base_url: '/'
98
99
  )
99
100
  end
100
101
 
102
+ # @param marker [String]
103
+ # @return [String]
104
+ def event_marker_path(marker)
105
+ build_path({ filter: { markers: [escape_empty_string(marker)] } }, base_url: '/')
106
+ end
107
+
101
108
  # @param str [String]
102
109
  # @return [String]
103
110
  def empty_characters_fallback(str)
@@ -113,16 +120,16 @@ module PgEventstore
113
120
  def build_starting_id_link(starting_id)
114
121
  return 'javascript: void(0);' unless starting_id
115
122
 
116
- build_path(params.merge(starting_id: starting_id))
123
+ build_path(params.merge(starting_id:))
117
124
  end
118
125
 
119
126
  # @param params [Hash, Array]
120
127
  # @return [String]
121
- def build_path(params)
128
+ def build_path(params, base_url: request.path)
122
129
  encoded_params = Rack::Utils.build_nested_query(params)
123
- return request.path if encoded_params.empty?
130
+ return base_url if encoded_params.empty?
124
131
 
125
- "#{request.path}?#{encoded_params}"
132
+ "#{base_url}?#{encoded_params}"
126
133
  end
127
134
  end
128
135
  end
@@ -0,0 +1,48 @@
1
+ # frozen_string_literal: true
2
+
3
+ module PgEventstore
4
+ module Web
5
+ module Paginator
6
+ class MarkersCollection < BaseCollection
7
+ # @return [Integer]
8
+ PER_PAGE = 10
9
+
10
+ # @return [Array<Hash<String => String>>]
11
+ def collection
12
+ @collection ||=
13
+ begin
14
+ sql_builder = SQLBuilder.new.select('name').from('event_markers')
15
+ sql_builder.where("name #{direction_operator} ?", starting_id) if starting_id
16
+ sql_builder.where('name like ?', "#{options[:query]}%")
17
+ sql_builder.order("name #{order}").limit(per_page)
18
+ connection.with do |conn|
19
+ conn.exec_params(*sql_builder.to_exec_params)
20
+ end.to_a
21
+ end
22
+ end
23
+
24
+ # @return [String, nil]
25
+ def next_page_starting_id
26
+ return unless collection.size == per_page
27
+
28
+ starting_id = collection.first['name']
29
+ sql_builder = SQLBuilder.new.select('name').from('event_markers')
30
+ sql_builder.where("name #{direction_operator} ?", starting_id)
31
+ sql_builder.where('name like ?', "#{options[:query]}%")
32
+ sql_builder.order("name #{order}").limit(1).offset(per_page)
33
+
34
+ connection.with do |conn|
35
+ conn.exec_params(*sql_builder.to_exec_params)
36
+ end.to_a.dig(0, 'name')
37
+ end
38
+
39
+ private
40
+
41
+ # @return [String]
42
+ def direction_operator
43
+ order == :asc ? '>=' : '<='
44
+ end
45
+ end
46
+ end
47
+ end
48
+ end
@@ -14,7 +14,7 @@ module PgEventstore
14
14
  sql_builder = SQLBuilder.new.select('context').from('partitions')
15
15
  sql_builder.where('stream_name is null and event_type is null')
16
16
  sql_builder.where("context #{direction_operator} ?", starting_id) if starting_id
17
- sql_builder.where('context ilike ?', "%#{options[:query]}%")
17
+ compute_context_filter(sql_builder)
18
18
  sql_builder.limit(per_page).order("context #{order}")
19
19
  connection.with do |conn|
20
20
  conn.exec_params(*sql_builder.to_exec_params)
@@ -30,7 +30,7 @@ module PgEventstore
30
30
  sql_builder = SQLBuilder.new.select('context').from('partitions')
31
31
  sql_builder.where('stream_name is null and event_type is null')
32
32
  sql_builder.where("context #{direction_operator} ?", starting_id)
33
- sql_builder.where('context ilike ?', "%#{options[:query]}%")
33
+ compute_context_filter(sql_builder)
34
34
  sql_builder.limit(1).offset(per_page).order("context #{order}")
35
35
 
36
36
  connection.with do |conn|
@@ -44,6 +44,17 @@ module PgEventstore
44
44
  def direction_operator
45
45
  order == :asc ? '>=' : '<='
46
46
  end
47
+
48
+ # @param builder [PgEventstore::SQLBuilder]
49
+ # @return [void]
50
+ def compute_context_filter(builder)
51
+ query = options[:query].to_s
52
+ if query.size < MIN_QUERY_SIZE_FOR_ADVANCE_SEARCH
53
+ builder.where('context like ?', "#{query}%")
54
+ else
55
+ builder.where('context ilike ?', "%#{query}%")
56
+ end
57
+ end
47
58
  end
48
59
  end
49
60
  end
@@ -11,11 +11,9 @@ module PgEventstore
11
11
  def collection
12
12
  @collection ||=
13
13
  begin
14
- sql_builder = SQLBuilder.new.select('stream_id').from(Event::PRIMARY_TABLE_NAME)
15
- sql_builder.where('context = ? and stream_name = ?', options[:context], options[:stream_name])
16
- sql_builder.where('stream_id like ?', "#{options[:query]}%")
17
- sql_builder.where("stream_id #{direction_operator} ?", starting_id) if starting_id
18
- sql_builder.group('stream_id').limit(per_page).order("stream_id #{order}")
14
+ sql_builder = streams_index_sql_builder(from_id: starting_id)
15
+ sql_builder.limit(per_page)
16
+
19
17
  connection.with do |conn|
20
18
  conn.exec_params(*sql_builder.to_exec_params)
21
19
  end.to_a
@@ -26,12 +24,8 @@ module PgEventstore
26
24
  def next_page_starting_id
27
25
  return unless collection.size == per_page
28
26
 
29
- starting_id = collection.first['stream_id']
30
- sql_builder = SQLBuilder.new.select('stream_id').from(Event::PRIMARY_TABLE_NAME)
31
- sql_builder.where("stream_id #{direction_operator} ?", starting_id)
32
- sql_builder.where('stream_id like ?', "#{options[:query]}%")
33
- sql_builder.where('context = ? and stream_name = ?', options[:context], options[:stream_name])
34
- sql_builder.group('stream_id').limit(1).offset(per_page).order("stream_id #{order}")
27
+ sql_builder = streams_index_sql_builder(from_id: collection.first['stream_id'])
28
+ sql_builder.limit(1).offset(per_page)
35
29
 
36
30
  connection.with do |conn|
37
31
  conn.exec_params(*sql_builder.to_exec_params)
@@ -40,6 +34,22 @@ module PgEventstore
40
34
 
41
35
  private
42
36
 
37
+ def partitions_sql_builder
38
+ filters = QueryBuilders::Filters::Collection.from_options(
39
+ { filter: { streams: [{ context: options[:context], stream_name: options[:stream_name] }] } }
40
+ )
41
+ QueryBuilders::PartitionsFiltering.assemble_sql_builder(filters, scope: :stream_name).unselect.select('id')
42
+ end
43
+
44
+ def streams_index_sql_builder(from_id: nil)
45
+ sql_builder = SQLBuilder.new.select('stream_id')
46
+ sql_builder.from(QueryBuilders::StreamsGlobalIndexFiltering::PRIMARY_TABLE_NAME)
47
+ sql_builder.where('partition_id = ?', partitions_sql_builder)
48
+ sql_builder.where('stream_id like ?', "#{options[:query]}%")
49
+ sql_builder.where("stream_id #{direction_operator} ?", from_id) if from_id
50
+ sql_builder.order("stream_id #{order}")
51
+ end
52
+
43
53
  # @return [String]
44
54
  def direction_operator
45
55
  order == :asc ? '>=' : '<='
@@ -12,9 +12,9 @@ module PgEventstore
12
12
  @collection ||=
13
13
  begin
14
14
  sql_builder = SQLBuilder.new.select('stream_name').from('partitions')
15
- sql_builder.where('event_type is null and context = ?', options[:context])
16
- sql_builder.where('stream_name ilike ?', "%#{options[:query]}%")
15
+ sql_builder.where('event_type is null and stream_name is not null and context = ?', options[:context])
17
16
  sql_builder.where("stream_name #{direction_operator} ?", starting_id) if starting_id
17
+ compute_stream_name_filter(sql_builder)
18
18
  sql_builder.limit(per_page).order("stream_name #{order}")
19
19
  connection.with do |conn|
20
20
  conn.exec_params(*sql_builder.to_exec_params)
@@ -29,10 +29,9 @@ module PgEventstore
29
29
  starting_id = collection.first['stream_name']
30
30
  sql_builder = SQLBuilder.new.select('stream_name').from('partitions')
31
31
  sql_builder.where("stream_name #{direction_operator} ?", starting_id)
32
- sql_builder.where('stream_name ilike ?', "%#{options[:query]}%")
32
+ compute_stream_name_filter(sql_builder)
33
33
  sql_builder.where('event_type is null and context = ?', options[:context])
34
34
  sql_builder.limit(1).offset(per_page).order("stream_name #{order}")
35
-
36
35
  connection.with do |conn|
37
36
  conn.exec_params(*sql_builder.to_exec_params)
38
37
  end.to_a.dig(0, 'stream_name')
@@ -44,6 +43,21 @@ module PgEventstore
44
43
  def direction_operator
45
44
  order == :asc ? '>=' : '<='
46
45
  end
46
+
47
+ # @param builder [PgEventstore::SQLBuilder]
48
+ # @return [void]
49
+ def compute_stream_name_filter(builder)
50
+ query = options[:query].to_s
51
+ if query.size < MIN_QUERY_SIZE_FOR_ADVANCE_SEARCH
52
+ builder.where('stream_name like ?', "#{query}%")
53
+ else
54
+ builder.where(
55
+ 'context || ? || stream_name ilike ?',
56
+ PgEventstore::Event::SYSTEM_SYMBOL,
57
+ "#{options[:context]}#{PgEventstore::Event::SYSTEM_SYMBOL}%#{query}%"
58
+ )
59
+ end
60
+ end
47
61
  end
48
62
  end
49
63
  end
@@ -0,0 +1,95 @@
1
+ # frozen_string_literal: true
2
+
3
+ module PgEventstore
4
+ module Web
5
+ module Paginator
6
+ class StreamsCollection < BaseCollection
7
+ # @return [Hash<String => Symbol>] SQL directions, string-to-symbol mapping
8
+ SQL_DIRECTIONS = {
9
+ 'asc' => :asc,
10
+ 'desc' => :desc,
11
+ }.tap do |directions|
12
+ directions.default = :desc
13
+ end.freeze
14
+ # @return [Hash<String => Integer>] per page limits, string to Integer mapping
15
+ PER_PAGE = %w[10 20 50 100 1000].to_h { [_1, _1.to_i] }.tap do |per_page|
16
+ per_page.default = 10
17
+ end.freeze
18
+ # @return [Integer] max number of events after which we don't perform the exact count and keep the estimate
19
+ # count instead because of the potential performance degradation.
20
+ MAX_NUMBER_TO_COUNT = 10_000
21
+
22
+ # @return [Array<PgEventstore::Stream>]
23
+ def collection
24
+ @collection ||= PgEventstore.client(config_name).read_streams(
25
+ options: { from_position: starting_id, max_count: per_page, direction: order }
26
+ )
27
+ end
28
+
29
+ # @return [Integer, nil]
30
+ def next_page_starting_id
31
+ return unless collection.size == per_page
32
+
33
+ from_position = collection.first&.starting_position
34
+ sql_builder = QueryBuilders::StreamsGlobalIndexFiltering.sql_builder_for_basic_pagination(
35
+ from_position:, max_count: 1, direction: order
36
+ ).unselect.select('starting_position').offset(per_page)
37
+ starting_position(sql_builder)
38
+ end
39
+
40
+ # @return [Integer, nil]
41
+ def prev_page_starting_id
42
+ from_position = collection.first&.starting_position || starting_id
43
+ sql_builder = QueryBuilders::StreamsGlobalIndexFiltering.sql_builder_for_basic_pagination(
44
+ from_position:, max_count: per_page, direction: order == :asc ? :desc : :asc
45
+ ).unselect.select('starting_position').offset(1)
46
+ sql_builder = SQLBuilder.new.select('starting_position').from(sql_builder)
47
+ sql_builder.order("starting_position #{order}").limit(1)
48
+ starting_position(sql_builder)
49
+ end
50
+
51
+ # @return [Integer]
52
+ def total_count
53
+ @total_count ||=
54
+ begin
55
+ sql_builder = QueryBuilders::StreamsGlobalIndexFiltering.sql_builder_for_basic_pagination({})
56
+ sql_builder.remove_limit.remove_group.remove_order
57
+ count = estimate_count(sql_builder)
58
+ return count if count > MAX_NUMBER_TO_COUNT
59
+
60
+ regular_count(sql_builder)
61
+ end
62
+ end
63
+
64
+ private
65
+
66
+ # @param sql_builder [PgEventstore::SQLBuilder]
67
+ # @return [Integer]
68
+ def estimate_count(sql_builder)
69
+ sql, params = sql_builder.to_exec_params
70
+ connection.with do |conn|
71
+ conn.exec_params("EXPLAIN #{sql}", params)
72
+ end.to_a.first['QUERY PLAN'].match(/rows=(\d+)/)[1].to_i
73
+ end
74
+
75
+ # @param sql_builder [PgEventstore::SQLBuilder]
76
+ # @return [Integer]
77
+ def regular_count(sql_builder)
78
+ sql_builder.unselect.select('count(*) as count_all')
79
+
80
+ connection.with do |conn|
81
+ conn.exec_params(*sql_builder.to_exec_params)
82
+ end.to_a.first['count_all']
83
+ end
84
+
85
+ # @param sql_builder [PgEventstore::SQLBuilder]
86
+ # @return [Integer, nil]
87
+ def starting_position(sql_builder)
88
+ connection.with do |conn|
89
+ conn.exec_params(*sql_builder.to_exec_params)
90
+ end.to_a.dig(0, 'starting_position')
91
+ end
92
+ end
93
+ end
94
+ end
95
+ end
@@ -98,15 +98,9 @@ $(function(){
98
98
  $streamIdSelect.on('change.select2', removeDeleteBtn);
99
99
  }
100
100
 
101
- let initSystemStreamFilterAutocomplete = function($filter){
102
- let $streamNameSelect = $filter.find('select');
103
- $streamNameSelect.select2({
104
- allowClear: true
105
- });
106
- }
107
-
108
101
  let initEventTypeFilterAutocomplete = function($filter) {
109
- let $eventTypeSelect = $filter.find('select');
102
+ let $eventTypeSelect = $filter.find('select.type-filter');
103
+ let $eventMarkersSelect = $filter.find('select.event-markers-filter');
110
104
  $eventTypeSelect.select2({
111
105
  ajax: {
112
106
  url: $eventTypeSelect.data('url'),
@@ -123,6 +117,42 @@ $(function(){
123
117
  templateSelection: templateSelection,
124
118
  templateResult: templateResult,
125
119
  });
120
+ $eventMarkersSelect.select2({
121
+ ajax: {
122
+ url: $eventMarkersSelect.data('url'),
123
+ processResults: function(data, params){
124
+ params.starting_id = data.pagination.starting_id;
125
+ data.results.forEach(function(contextAttrs){
126
+ contextAttrs.id = contextAttrs.name;
127
+ contextAttrs.text = contextAttrs.name;
128
+ });
129
+ return data;
130
+ },
131
+ },
132
+ allowClear: true,
133
+ templateSelection: templateSelection,
134
+ templateResult: templateResult,
135
+ });
136
+ }
137
+
138
+ let initMarkersFilterAutocomplete = function($filter) {
139
+ let $markersSelect = $filter.find('select.markers-filter');
140
+ $markersSelect.select2({
141
+ ajax: {
142
+ url: $markersSelect.data('url'),
143
+ processResults: function(data, params){
144
+ params.starting_id = data.pagination.starting_id;
145
+ data.results.forEach(function(contextAttrs){
146
+ contextAttrs.id = contextAttrs.name;
147
+ contextAttrs.text = contextAttrs.name;
148
+ });
149
+ return data;
150
+ },
151
+ },
152
+ allowClear: true,
153
+ templateSelection: templateSelection,
154
+ templateResult: templateResult,
155
+ });
126
156
  }
127
157
 
128
158
  // Per page drop down
@@ -133,10 +163,10 @@ $(function(){
133
163
  let $filtersForm = $('#filters-form');
134
164
  // Stream filter template
135
165
  let streamFilterTmpl = $('#stream-filter-tmpl').text();
136
- // System stream filter template
137
- let systemStreamFilterTmpl = $('#system-stream-filter-tmpl').text();
138
166
  // Event type filter template
139
167
  let eventFilterTmpl = $('#event-type-filter-tmpl').text();
168
+ // Markers filter template
169
+ let markersFilterTmpl = $('#markers-filter-tmpl').text();
140
170
 
141
171
  // Remove filter button
142
172
  $filtersForm.on('click', '.remove-filter', function(){
@@ -148,19 +178,16 @@ $(function(){
148
178
  $filtersForm.find('.stream-filters').append(streamFilterTmpl.replace(/%NUM%/g, filtersNum));
149
179
  initStreamFilterAutocomplete($filtersForm.find('.stream-filters').children().last());
150
180
  });
151
- // "Add system stream filter" button
152
- $filtersForm.on('click', '.add-system-stream-filter', function(){
153
- if($filtersForm.find('.system-stream-filter').children().length > 0)
154
- return;
155
-
156
- $filtersForm.find('.system-stream-filter').append(systemStreamFilterTmpl);
157
- initSystemStreamFilterAutocomplete($filtersForm.find('.system-stream-filter').children().last());
158
- });
159
181
  // "Add event type filter" button
160
182
  $filtersForm.on('click', '.add-event-filter', function(){
161
183
  $filtersForm.find('.event-filters').append(eventFilterTmpl);
162
184
  initEventTypeFilterAutocomplete($filtersForm.find('.event-filters').children().last());
163
185
  });
186
+ // "Add markers filter" button
187
+ $filtersForm.on('click', '.add-markers-filter', function(){
188
+ $filtersForm.find('.markers-filter').append(markersFilterTmpl);
189
+ initMarkersFilterAutocomplete($filtersForm.find('div.markers-filter').children().last());
190
+ });
164
191
 
165
192
  // Because zero-byte character can't be rendered into HTML properly - loop through each option, marked as containing
166
193
  // zero-byte value and assign zero-byte value explicitly. This must be done before we initialize select2 plugin.
@@ -171,14 +198,14 @@ $(function(){
171
198
  $filtersForm.find('.stream-filters').children().each(function(){
172
199
  initStreamFilterAutocomplete($(this));
173
200
  });
174
- // Init select2 for system stream filter which were initially rendered
175
- $filtersForm.find('.system-stream-filter').children().each(function(){
176
- initSystemStreamFilterAutocomplete($(this));
177
- });
178
201
  // Init select2 for event type filters which were initially rendered
179
202
  $filtersForm.find('.event-filters').children().each(function(){
180
203
  initEventTypeFilterAutocomplete($(this));
181
204
  });
205
+ // Init select2 for markers filter which was initially rendered
206
+ $filtersForm.find('.markers-filter').children().each(function(){
207
+ initMarkersFilterAutocomplete($(this));
208
+ });
182
209
 
183
210
  // Automatically refresh events list every two seconds
184
211
  let autoRefreshInterval;
@@ -9,7 +9,7 @@ module PgEventstore
9
9
  def subscriptions_url(set_name: nil)
10
10
  return url('/subscriptions') unless set_name
11
11
 
12
- encoded_params = Rack::Utils.build_nested_query(set_name: set_name)
12
+ encoded_params = Rack::Utils.build_nested_query(set_name:)
13
13
  url("/subscriptions?#{encoded_params}")
14
14
  end
15
15
 
@@ -117,7 +117,7 @@ module PgEventstore
117
117
  # @param ids [Array<Integer>]
118
118
  # @return [String]
119
119
  def delete_all_subscriptions_url(ids)
120
- encoded_params = Rack::Utils.build_nested_query(ids: ids)
120
+ encoded_params = Rack::Utils.build_nested_query(ids:)
121
121
  url("/delete_all_subscriptions?#{encoded_params}")
122
122
  end
123
123
 
@@ -23,7 +23,7 @@ module PgEventstore
23
23
 
24
24
  # @return [PgEventstore::SubscriptionQueries]
25
25
  def subscription_queries
26
- SubscriptionQueries.new(connection)
26
+ SubscriptionQueries.new(connection, QueryStrategy::Foreground.new(connection))
27
27
  end
28
28
 
29
29
  # @return [PgEventstore::SubscriptionsSetQueries]
@@ -27,7 +27,7 @@ module PgEventstore
27
27
 
28
28
  # @return [PgEventstore::SubscriptionQueries]
29
29
  def subscription_queries
30
- SubscriptionQueries.new(connection)
30
+ SubscriptionQueries.new(connection, QueryStrategy::Foreground.new(connection))
31
31
  end
32
32
  end
33
33
  end
@@ -26,7 +26,7 @@ module PgEventstore
26
26
 
27
27
  # @return [PgEventstore::SubscriptionQueries]
28
28
  def subscription_queries
29
- SubscriptionQueries.new(connection)
29
+ SubscriptionQueries.new(connection, QueryStrategy::Foreground.new(connection))
30
30
  end
31
31
  end
32
32
  end
@@ -30,7 +30,7 @@ module PgEventstore
30
30
 
31
31
  # @return [PgEventstore::SubscriptionQueries]
32
32
  def subscription_queries
33
- SubscriptionQueries.new(connection)
33
+ SubscriptionQueries.new(connection, QueryStrategy::Foreground.new(connection))
34
34
  end
35
35
  end
36
36
  end