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.
- checksums.yaml +4 -4
- data/.rubocop.yml +11 -2
- data/CHANGELOG.md +195 -16
- data/README.md +33 -10
- data/db/migrations/10_setup_pg_cron.rb +1 -0
- data/db/migrations/11_add_events_link_global_position.sql +1 -0
- data/db/migrations/12_migrate_legacy_links.rb +83 -0
- data/db/migrations/13_remove_events_link_id.sql +6 -0
- data/db/migrations/14_remove_ids_events_id_index.sql +1 -0
- data/db/migrations/15_create_streams_global_index.sql +17 -0
- data/db/migrations/16_populate_streams_global_index.rb +150 -0
- data/db/migrations/17_create_events_global_index.sql +62 -0
- data/db/migrations/18_populate_events_global_index.rb +124 -0
- data/db/migrations/19_populate_events_global_index_p2.rb +25 -0
- data/db/migrations/20_migrate_subscriptions_current_position.sql +19 -0
- data/db/migrations/21_create_partitions_stats.sql +2 -0
- data/db/migrations/22_drop_streams_sql_view.sql +2 -0
- data/db/migrations/23_adjust_partitions_indexes.sql +5 -0
- data/db/migrations/24_drop_legacy_events_indexes.sql +3 -0
- data/db/migrations/25_add_parent_partitions_info_to_partitions.sql +16 -0
- data/db/migrations/26_change_events_stream_revision_type.rb +35 -0
- data/db/migrations/27_drop_events_horizon.sql +3 -0
- data/db/migrations/28_create_maintenance_tasks.sql +8 -0
- data/db/migrations/29_create_event_markers.sql +35 -0
- data/db/migrations/30_improve_partitions_search_in_admin_ui.rb +24 -0
- data/db/migrations/31_drop_events_id_default_value.sql +1 -0
- data/db/migrations/32_create_parittions_triggers.sql +101 -0
- data/db/migrations/9_create_events_horizon.sql +21 -0
- data/docs/AGENTS.fragment.md +696 -0
- data/docs/admin_ui.md +3 -1
- data/docs/appending_events.md +110 -49
- data/docs/configuration.md +69 -36
- data/docs/event_tracing.md +55 -0
- data/docs/events_and_streams.md +54 -30
- data/docs/how_it_works.md +57 -16
- data/docs/linking_events.md +2 -1
- data/docs/maintenance.md +14 -5
- data/docs/multiple_commands.md +30 -6
- data/docs/reading_events.md +208 -43
- data/docs/reading_streams.md +50 -0
- data/docs/replication.md +99 -0
- data/docs/subscriptions.md +165 -35
- data/docs/writing_middleware.md +25 -8
- data/ext/pg_eventstore_ext/extconf.rb +5 -0
- data/ext/pg_eventstore_ext/pg_eventstore_ext.c +74 -0
- data/lib/pg_eventstore/async_runner.rb +63 -0
- data/lib/pg_eventstore/basic_config.rb +15 -0
- data/lib/pg_eventstore/callbacks.rb +7 -5
- data/lib/pg_eventstore/chunks/chunk.rb +31 -0
- data/lib/pg_eventstore/chunks/read_api_events_index_chunk.rb +83 -0
- data/lib/pg_eventstore/chunks/replica_events_index_chunk.rb +35 -0
- data/lib/pg_eventstore/chunks/repository.rb +73 -0
- data/lib/pg_eventstore/chunks/subscription_checkpoint_chunk.rb +48 -0
- data/lib/pg_eventstore/chunks/subscription_events_index_chunk.rb +99 -0
- data/lib/pg_eventstore/chunks.rb +14 -0
- data/lib/pg_eventstore/cli/try_to_delete_subscriptions_set.rb +2 -2
- data/lib/pg_eventstore/client.rb +167 -52
- data/lib/pg_eventstore/commands/append.rb +62 -43
- data/lib/pg_eventstore/commands/delete_event.rb +7 -8
- data/lib/pg_eventstore/commands/delete_stream.rb +3 -3
- data/lib/pg_eventstore/commands/event_modifiers/prepare_link_event.rb +11 -6
- data/lib/pg_eventstore/commands/event_modifiers/prepare_regular_event.rb +12 -7
- data/lib/pg_eventstore/commands/link_to.rb +9 -9
- data/lib/pg_eventstore/commands/multiple.rb +2 -2
- data/lib/pg_eventstore/commands/read.rb +23 -5
- data/lib/pg_eventstore/commands/read_grouped.rb +46 -0
- data/lib/pg_eventstore/commands/read_streams.rb +18 -0
- data/lib/pg_eventstore/commands/read_streams_paginated.rb +56 -0
- data/lib/pg_eventstore/commands/regular_stream_read_paginated.rb +4 -4
- data/lib/pg_eventstore/commands/revision_check/current_revision.rb +51 -0
- data/lib/pg_eventstore/commands/revision_check/event_type_revisions_comparison.rb +46 -0
- data/lib/pg_eventstore/commands/revision_check/expected_revision.rb +135 -0
- data/lib/pg_eventstore/commands/revision_check/stream_revision_check.rb +98 -0
- data/lib/pg_eventstore/commands/revision_check/stream_revision_comparison.rb +36 -0
- data/lib/pg_eventstore/commands/stream_revision.rb +14 -0
- data/lib/pg_eventstore/commands/system_stream_read_paginated.rb +4 -4
- data/lib/pg_eventstore/commands.rb +4 -2
- data/lib/pg_eventstore/config.rb +30 -9
- data/lib/pg_eventstore/connection.rb +22 -37
- data/lib/pg_eventstore/errors.rb +137 -11
- data/lib/pg_eventstore/event.rb +39 -7
- data/lib/pg_eventstore/event_deserializer.rb +5 -4
- data/lib/pg_eventstore/event_global_index.rb +118 -0
- data/lib/pg_eventstore/event_marker.rb +16 -0
- data/lib/pg_eventstore/event_marker_index.rb +25 -0
- data/lib/pg_eventstore/event_serializer.rb +6 -0
- data/lib/pg_eventstore/extensions/acts_as_configurable.rb +88 -0
- data/lib/pg_eventstore/extensions/options_defaults.rb +25 -0
- data/lib/pg_eventstore/extensions/options_extension.rb +42 -13
- data/lib/pg_eventstore/feature_marker.rb +18 -0
- data/lib/pg_eventstore/maintenance.rb +11 -6
- data/lib/pg_eventstore/middleware/event_tracing.rb +53 -0
- data/lib/pg_eventstore/partition.rb +6 -0
- data/lib/pg_eventstore/pg_connection.rb +70 -14
- data/lib/pg_eventstore/queries/event_marker_queries.rb +74 -0
- data/lib/pg_eventstore/queries/event_queries.rb +9 -95
- data/lib/pg_eventstore/queries/events_global_index_queries.rb +131 -0
- data/lib/pg_eventstore/queries/index_filtering_queries.rb +179 -0
- data/lib/pg_eventstore/queries/links_resolver.rb +10 -7
- data/lib/pg_eventstore/queries/maintenance_queries.rb +159 -42
- data/lib/pg_eventstore/queries/partition_queries.rb +46 -104
- data/lib/pg_eventstore/queries/replica_queries.rb +110 -0
- data/lib/pg_eventstore/queries/streams_global_index_queries.rb +163 -0
- data/lib/pg_eventstore/queries/transaction_queries.rb +58 -10
- data/lib/pg_eventstore/queries.rb +29 -1
- data/lib/pg_eventstore/query_builders/basic_filtering.rb +38 -5
- data/lib/pg_eventstore/query_builders/event_markers_filtering.rb +47 -0
- data/lib/pg_eventstore/query_builders/event_markers_index_filtering.rb +275 -0
- data/lib/pg_eventstore/query_builders/event_subscription_positions_filtering.rb +37 -0
- data/lib/pg_eventstore/query_builders/events_filtering.rb +15 -164
- data/lib/pg_eventstore/query_builders/events_global_index_filtering.rb +227 -0
- data/lib/pg_eventstore/query_builders/filters/collection.rb +324 -0
- data/lib/pg_eventstore/query_builders/filters/event_type_filter.rb +37 -0
- data/lib/pg_eventstore/query_builders/filters/filter_row.rb +54 -0
- data/lib/pg_eventstore/query_builders/filters/marker_filter.rb +20 -0
- data/lib/pg_eventstore/query_builders/filters/marker_filter_row.rb +49 -0
- data/lib/pg_eventstore/query_builders/filters/stream_filter.rb +48 -0
- data/lib/pg_eventstore/query_builders/index_based_events_filtering.rb +260 -0
- data/lib/pg_eventstore/query_builders/partitions_filtering.rb +175 -51
- data/lib/pg_eventstore/query_builders/read_cursor/stream_cursor.rb +122 -0
- data/lib/pg_eventstore/query_builders/streams_global_index_filtering.rb +83 -0
- data/lib/pg_eventstore/query_builders/subscription_events_filtering.rb +79 -0
- data/lib/pg_eventstore/query_strategy/async.rb +64 -0
- data/lib/pg_eventstore/query_strategy/foreground.rb +25 -0
- data/lib/pg_eventstore/query_strategy.rb +19 -0
- data/lib/pg_eventstore/raw_event.rb +46 -0
- data/lib/pg_eventstore/rspec/test_helpers.rb +21 -8
- data/lib/pg_eventstore/sql_builder.rb +87 -8
- data/lib/pg_eventstore/stream.rb +14 -17
- data/lib/pg_eventstore/stream_global_index.rb +28 -0
- data/lib/pg_eventstore/subscriptions/basic_runner.rb +4 -4
- data/lib/pg_eventstore/subscriptions/callback_handlers/events_processor_handlers.rb +5 -17
- data/lib/pg_eventstore/subscriptions/callback_handlers/events_subscription_position_worker_handlers.rb +36 -0
- data/lib/pg_eventstore/subscriptions/callback_handlers/subscription_feeder_handlers.rb +13 -1
- data/lib/pg_eventstore/subscriptions/callback_handlers/subscription_runner_handlers.rb +19 -14
- data/lib/pg_eventstore/subscriptions/events_processor.rb +21 -19
- data/lib/pg_eventstore/subscriptions/events_processor_consumer/multiple.rb +63 -0
- data/lib/pg_eventstore/subscriptions/events_processor_consumer/replica.rb +68 -0
- data/lib/pg_eventstore/subscriptions/events_processor_consumer/single.rb +62 -0
- data/lib/pg_eventstore/subscriptions/events_processor_consumer.rb +44 -0
- data/lib/pg_eventstore/subscriptions/events_subscription_position_worker.rb +68 -0
- data/lib/pg_eventstore/subscriptions/queries/event_subscription_position_queries.rb +177 -0
- data/lib/pg_eventstore/subscriptions/queries/subscription_command_queries.rb +5 -5
- data/lib/pg_eventstore/subscriptions/queries/subscription_queries.rb +80 -56
- data/lib/pg_eventstore/subscriptions/queries/subscriptions_set_command_queries.rb +2 -2
- data/lib/pg_eventstore/subscriptions/queries/subscriptions_set_queries.rb +1 -1
- data/lib/pg_eventstore/subscriptions/replica_subscription_handler.rb +140 -0
- data/lib/pg_eventstore/subscriptions/replica_subscription_runner.rb +9 -0
- data/lib/pg_eventstore/subscriptions/subscription.rb +9 -7
- data/lib/pg_eventstore/subscriptions/subscription_feed_strategies/collection.rb +36 -0
- data/lib/pg_eventstore/subscriptions/subscription_feed_strategies/index_read_strategy.rb +82 -0
- data/lib/pg_eventstore/subscriptions/subscription_feed_strategies/replication_strategy.rb +75 -0
- data/lib/pg_eventstore/subscriptions/subscription_feed_strategy.rb +31 -0
- data/lib/pg_eventstore/subscriptions/subscription_feeder.rb +26 -2
- data/lib/pg_eventstore/subscriptions/subscription_handler_performance.rb +5 -5
- data/lib/pg_eventstore/subscriptions/subscription_runner.rb +20 -22
- data/lib/pg_eventstore/subscriptions/subscription_runner_commands/reset_position.rb +1 -1
- data/lib/pg_eventstore/subscriptions/subscription_runners_feeder.rb +10 -11
- data/lib/pg_eventstore/subscriptions/subscriptions_lifecycle.rb +0 -12
- data/lib/pg_eventstore/subscriptions/subscriptions_manager.rb +84 -29
- data/lib/pg_eventstore/{subscriptions/synchronized_array.rb → synchronized_array.rb} +15 -0
- data/lib/pg_eventstore/tasks/setup.rake +32 -33
- data/lib/pg_eventstore/utils.rb +39 -0
- data/lib/pg_eventstore/version.rb +1 -1
- data/lib/pg_eventstore/web/application.rb +104 -20
- data/lib/pg_eventstore/web/paginator/base_collection.rb +5 -1
- data/lib/pg_eventstore/web/paginator/event_types_collection.rb +14 -4
- data/lib/pg_eventstore/web/paginator/events_collection.rb +29 -33
- data/lib/pg_eventstore/web/paginator/helpers.rb +19 -12
- data/lib/pg_eventstore/web/paginator/markers_collection.rb +48 -0
- data/lib/pg_eventstore/web/paginator/stream_contexts_collection.rb +13 -2
- data/lib/pg_eventstore/web/paginator/stream_ids_collection.rb +21 -11
- data/lib/pg_eventstore/web/paginator/stream_names_collection.rb +18 -4
- data/lib/pg_eventstore/web/paginator/streams_collection.rb +95 -0
- data/lib/pg_eventstore/web/public/javascripts/pg_eventstore.js +49 -22
- data/lib/pg_eventstore/web/subscriptions/helpers.rb +2 -2
- data/lib/pg_eventstore/web/subscriptions/set_collection.rb +1 -1
- data/lib/pg_eventstore/web/subscriptions/subscriptions.rb +1 -1
- data/lib/pg_eventstore/web/subscriptions/with_state/set_collection.rb +1 -1
- data/lib/pg_eventstore/web/subscriptions/with_state/subscriptions.rb +1 -1
- data/lib/pg_eventstore/web/views/home/dashboard.erb +11 -9
- data/lib/pg_eventstore/web/views/home/partials/event_filter.erb +18 -5
- data/lib/pg_eventstore/web/views/home/partials/events.erb +38 -1
- data/lib/pg_eventstore/web/views/home/partials/markers_filter.erb +18 -0
- data/lib/pg_eventstore/web/views/layouts/application.erb +6 -0
- data/lib/pg_eventstore/web/views/streams/index.erb +110 -0
- data/lib/pg_eventstore/web/views/streams/partials/streams.erb +11 -0
- data/lib/pg_eventstore/web/views/subscriptions/index.erb +4 -1
- data/lib/pg_eventstore/web.rb +2 -0
- data/lib/pg_eventstore.rb +26 -63
- data/pg_eventstore.gemspec +6 -4
- data/sig/interfaces/_raw_events_handler.rbs +3 -0
- data/sig/interfaces/subscription_handler.rbs +1 -1
- data/sig/pg/result.rbs +9 -0
- data/sig/pg_eventstore/async_runner.rbs +13 -0
- data/sig/pg_eventstore/basic_config.rbs +9 -0
- data/sig/pg_eventstore/chunks/chunk.rbs +13 -0
- data/sig/pg_eventstore/chunks/read_api_events_index_chunk.rbs +30 -0
- data/sig/pg_eventstore/chunks/replica_events_index_chunk.rbs +11 -0
- data/sig/pg_eventstore/chunks/repository.rbs +22 -0
- data/sig/pg_eventstore/chunks/subscription_checkpoint_chunk.rbs +18 -0
- data/sig/pg_eventstore/chunks/subscription_events_index_chunk.rbs +37 -0
- data/sig/pg_eventstore/client.rbs +41 -43
- data/sig/pg_eventstore/commands/append.rbs +11 -25
- data/sig/pg_eventstore/commands/event_modifiers/prepare_link_event.rbs +9 -12
- data/sig/pg_eventstore/commands/event_modifiers/prepare_regular_event.rbs +5 -4
- data/sig/pg_eventstore/commands/link_to.rbs +6 -11
- data/sig/pg_eventstore/commands/multiple.rbs +1 -1
- data/sig/pg_eventstore/commands/read.rbs +2 -5
- data/sig/pg_eventstore/commands/read_grouped.rbs +7 -0
- data/sig/pg_eventstore/commands/read_streams.rbs +7 -0
- data/sig/pg_eventstore/commands/read_streams_paginated.rbs +16 -0
- data/sig/pg_eventstore/commands/regular_stream_read_paginated.rbs +9 -17
- data/sig/pg_eventstore/commands/revision_check/current_revision.rbs +25 -0
- data/sig/pg_eventstore/commands/revision_check/event_type_revisions_comparison.rbs +14 -0
- data/sig/pg_eventstore/commands/revision_check/expected_revision.rbs +67 -0
- data/sig/pg_eventstore/commands/revision_check/stream_revision_check.rbs +20 -0
- data/sig/pg_eventstore/commands/revision_check/stream_revision_comparison.rbs +9 -0
- data/sig/pg_eventstore/commands/stream_revision.rbs +7 -0
- data/sig/pg_eventstore/commands/system_stream_read_paginated.rbs +9 -14
- data/sig/pg_eventstore/config.rbs +15 -6
- data/sig/pg_eventstore/connection.rbs +11 -18
- data/sig/pg_eventstore/errors.rbs +64 -34
- data/sig/pg_eventstore/event.rbs +20 -6
- data/sig/pg_eventstore/event_deserializer.rbs +5 -10
- data/sig/pg_eventstore/event_global_index.rbs +60 -0
- data/sig/pg_eventstore/event_marker.rbs +9 -0
- data/sig/pg_eventstore/event_marker_index.rbs +12 -0
- data/sig/pg_eventstore/extensions/acts_as_configurable.rbs +29 -0
- data/sig/pg_eventstore/extensions/options_defaults.rbs +7 -0
- data/sig/pg_eventstore/extensions/options_extension.rbs +9 -1
- data/sig/pg_eventstore/feature_marker.rbs +10 -0
- data/sig/pg_eventstore/maintenance.rbs +12 -8
- data/sig/pg_eventstore/middleware/event_trace.rbs +14 -0
- data/sig/pg_eventstore/partition.rbs +2 -4
- data/sig/pg_eventstore/pg_connection.rbs +8 -0
- data/sig/pg_eventstore/queries/event_marker_queries.rbs +21 -0
- data/sig/pg_eventstore/queries/event_queries.rbs +6 -38
- data/sig/pg_eventstore/queries/events_global_index_queries.rbs +37 -0
- data/sig/pg_eventstore/queries/index_filtering_queries.rbs +50 -0
- data/sig/pg_eventstore/queries/links_resolver.rbs +7 -11
- data/sig/pg_eventstore/queries/maintenance_queries.rbs +12 -9
- data/sig/pg_eventstore/queries/partition_queries.rbs +32 -67
- data/sig/pg_eventstore/queries/replica_queries.rbs +31 -0
- data/sig/pg_eventstore/queries/streams_global_index_queries.rbs +39 -0
- data/sig/pg_eventstore/queries/transaction_queries.rbs +4 -2
- data/sig/pg_eventstore/queries.rbs +11 -21
- data/sig/pg_eventstore/query_builders/basic_filtering.rbs +10 -3
- data/sig/pg_eventstore/query_builders/event_markers_filtering.rbs +17 -0
- data/sig/pg_eventstore/query_builders/event_markers_index_filtering.rbs +69 -0
- data/sig/pg_eventstore/query_builders/event_subscription_positions_filtering.rbs +15 -0
- data/sig/pg_eventstore/query_builders/events_filtering_query.rbs +9 -51
- data/sig/pg_eventstore/query_builders/events_global_index_filtering.rbs +68 -0
- data/sig/pg_eventstore/query_builders/filters/collection.rbs +84 -0
- data/sig/pg_eventstore/query_builders/filters/event_type_filter.rbs +19 -0
- data/sig/pg_eventstore/query_builders/filters/filter_row.rbs +21 -0
- data/sig/pg_eventstore/query_builders/filters/marker_filter.rbs +13 -0
- data/sig/pg_eventstore/query_builders/filters/marker_filter_row.rbs +19 -0
- data/sig/pg_eventstore/query_builders/filters/stream_filter.rbs +24 -0
- data/sig/pg_eventstore/query_builders/index_based_events_filtering.rbs +60 -0
- data/sig/pg_eventstore/query_builders/partitions_filtering.rbs +29 -10
- data/sig/pg_eventstore/query_builders/read_cursor/stream_cursor.rbs +47 -0
- data/sig/pg_eventstore/query_builders/streams_global_index_filtering.rbs +27 -0
- data/sig/pg_eventstore/query_builders/subscription_events_filtering.rbs +26 -0
- data/sig/pg_eventstore/query_strategy/async.rbs +17 -0
- data/sig/pg_eventstore/query_strategy/foreground.rbs +11 -0
- data/sig/pg_eventstore/query_strategy.rbs +7 -0
- data/sig/pg_eventstore/raw_event.rbs +20 -0
- data/sig/pg_eventstore/sql_builder.rbs +32 -10
- data/sig/pg_eventstore/stream.rbs +10 -18
- data/sig/pg_eventstore/stream_global_index.rbs +14 -0
- data/sig/pg_eventstore/subscriptions/callback_handlers/events_processor_handlers.rbs +5 -4
- data/sig/pg_eventstore/subscriptions/callback_handlers/events_subscription_position_worker_handlers.rbs +9 -0
- data/sig/pg_eventstore/subscriptions/callback_handlers/subscription_feeder_handlers.rbs +17 -12
- data/sig/pg_eventstore/subscriptions/callback_handlers/subscription_runner_handlers.rbs +16 -8
- data/sig/pg_eventstore/subscriptions/event_subscription_position_queries.rbs +30 -0
- data/sig/pg_eventstore/subscriptions/events_processor.rbs +12 -5
- data/sig/pg_eventstore/subscriptions/events_processor_consumer/multiple.rbs +17 -0
- data/sig/pg_eventstore/subscriptions/events_processor_consumer/replica.rbs +17 -0
- data/sig/pg_eventstore/subscriptions/events_processor_consumer/single.rbs +17 -0
- data/sig/pg_eventstore/subscriptions/events_processor_consumer.rbs +14 -0
- data/sig/pg_eventstore/subscriptions/events_subscription_position_worker.rbs +28 -0
- data/sig/pg_eventstore/subscriptions/queries/subscription_queries.rbs +18 -50
- data/sig/pg_eventstore/subscriptions/replica_subscription_handler.rbs +33 -0
- data/sig/pg_eventstore/subscriptions/replica_subscription_runner.rbs +4 -0
- data/sig/pg_eventstore/subscriptions/subscription_feed_strategy/collection.rbs +14 -0
- data/sig/pg_eventstore/subscriptions/subscription_feed_strategy/index_read_strategy.rbs +23 -0
- data/sig/pg_eventstore/subscriptions/subscription_feed_strategy/replication_strategy.rbs +23 -0
- data/sig/pg_eventstore/subscriptions/subscription_feed_strategy.rbs +11 -0
- data/sig/pg_eventstore/subscriptions/subscription_feeder.rbs +13 -10
- data/sig/pg_eventstore/subscriptions/subscription_handler_performance.rbs +1 -1
- data/sig/pg_eventstore/subscriptions/subscription_runner.rbs +13 -5
- data/sig/pg_eventstore/subscriptions/subscription_runners_feeder.rbs +5 -5
- data/sig/pg_eventstore/subscriptions/subscriptions_lifecycle.rbs +4 -6
- data/sig/pg_eventstore/subscriptions/subscriptions_manager.rbs +29 -43
- data/sig/pg_eventstore/synchronized_array.rbs +4 -0
- data/sig/pg_eventstore/utils.rbs +18 -11
- data/sig/pg_eventstore/web/application.rbs +13 -3
- data/sig/pg_eventstore/web/paginator/base_collection.rbs +2 -0
- data/sig/pg_eventstore/web/paginator/event_types_collection.rbs +4 -0
- data/sig/pg_eventstore/web/paginator/events_collection.rbs +11 -11
- data/sig/pg_eventstore/web/paginator/helpers.rbs +6 -15
- data/sig/pg_eventstore/web/paginator/markers_collection.rbs +13 -0
- data/sig/pg_eventstore/web/paginator/stream_contexts_collection.rbs +4 -0
- data/sig/pg_eventstore/web/paginator/stream_names_collection.rbs +4 -0
- data/sig/pg_eventstore/web/paginator/streams_collection.rbs +30 -0
- data/sig/pg_eventstore.rbs +8 -26
- metadata +181 -21
- data/lib/pg_eventstore/commands/all_stream_read_grouped.rb +0 -69
- data/lib/pg_eventstore/commands/regular_stream_read_grouped.rb +0 -31
- data/lib/pg_eventstore/subscriptions/queries/service_queries.rb +0 -73
- data/lib/pg_eventstore/subscriptions/subscription_position_evaluation.rb +0 -195
- data/lib/pg_eventstore/web/views/home/partials/system_stream_filter.erb +0 -15
- data/sig/pg_eventstore/commands/all_stream_read_grouped.rbs +0 -16
- data/sig/pg_eventstore/commands/regular_stream_read_grouped.rbs +0 -8
- data/sig/pg_eventstore/subscriptions/queries/service_queries.rbs +0 -15
- data/sig/pg_eventstore/subscriptions/subscription_position_evaluation.rbs +0 -53
- data/sig/pg_eventstore/subscriptions/synchronized_array.rbs +0 -4
- /data/sig/interfaces/{_raw_event_handler.rbs → raw_event_handler.rbs} +0 -0
|
@@ -6,19 +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 '
|
|
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
|
-
require_relative 'subscription_position_evaluation'
|
|
14
13
|
require_relative 'subscriptions_set'
|
|
14
|
+
require_relative 'subscription_feed_strategy'
|
|
15
15
|
require_relative 'subscription_runners_feeder'
|
|
16
16
|
require_relative 'subscriptions_set_lifecycle'
|
|
17
17
|
require_relative 'subscriptions_lifecycle'
|
|
18
18
|
require_relative 'callback_handlers/subscription_feeder_handlers'
|
|
19
19
|
require_relative 'callback_handlers/subscription_runner_handlers'
|
|
20
20
|
require_relative 'callback_handlers/events_processor_handlers'
|
|
21
|
+
require_relative 'callback_handlers/events_subscription_position_worker_handlers'
|
|
21
22
|
require_relative 'callback_handlers/commands_handler_handlers'
|
|
23
|
+
require_relative 'commands_handler'
|
|
24
|
+
require_relative 'events_subscription_position_worker'
|
|
22
25
|
require_relative 'subscription_feeder'
|
|
23
26
|
require_relative 'extensions/command_class_lookup_extension'
|
|
24
27
|
require_relative 'extensions/base_command_extension'
|
|
@@ -26,10 +29,11 @@ require_relative 'subscription_feeder_commands'
|
|
|
26
29
|
require_relative 'subscription_runner_commands'
|
|
27
30
|
require_relative 'queries/subscription_command_queries'
|
|
28
31
|
require_relative 'queries/subscription_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 '
|
|
32
|
-
require_relative '
|
|
35
|
+
require_relative 'replica_subscription_handler'
|
|
36
|
+
require_relative 'replica_subscription_runner'
|
|
33
37
|
|
|
34
38
|
module PgEventstore
|
|
35
39
|
# The public Subscriptions API, available to the user.
|
|
@@ -42,7 +46,6 @@ module PgEventstore
|
|
|
42
46
|
private :config
|
|
43
47
|
|
|
44
48
|
def_delegators :@subscription_feeder, :stop, :running?
|
|
45
|
-
def_delegators :@subscriptions_lifecycle, :force_lock!
|
|
46
49
|
|
|
47
50
|
# @param config [PgEventstore::Config]
|
|
48
51
|
# @param set_name [String]
|
|
@@ -61,10 +64,10 @@ module PgEventstore
|
|
|
61
64
|
}
|
|
62
65
|
)
|
|
63
66
|
@subscriptions_lifecycle = SubscriptionsLifecycle.new(
|
|
64
|
-
config_name, @subscriptions_set_lifecycle, force_lock:
|
|
67
|
+
config_name, @subscriptions_set_lifecycle, force_lock:
|
|
65
68
|
)
|
|
66
69
|
@subscription_feeder = SubscriptionFeeder.new(
|
|
67
|
-
config_name
|
|
70
|
+
config_name:,
|
|
68
71
|
subscriptions_set_lifecycle: @subscriptions_set_lifecycle,
|
|
69
72
|
subscriptions_lifecycle: @subscriptions_lifecycle
|
|
70
73
|
)
|
|
@@ -72,8 +75,8 @@ module PgEventstore
|
|
|
72
75
|
|
|
73
76
|
# @param subscription_name [String] subscription's name
|
|
74
77
|
# @param handler [#call] subscription's handler
|
|
75
|
-
# @param options [Hash]
|
|
76
|
-
# @option options [Integer
|
|
78
|
+
# @param options [Hash] subscription options
|
|
79
|
+
# @option options [Integer] :from_position a starting subscription position
|
|
77
80
|
# @option options [Boolean] :resolve_link_tos When using projections to create new events you
|
|
78
81
|
# can set whether the generated events are pointers to existing events. Setting this option to true tells
|
|
79
82
|
# PgEventstore to return the original event instead a link event.
|
|
@@ -92,6 +95,7 @@ module PgEventstore
|
|
|
92
95
|
# notification about failed subscription.
|
|
93
96
|
# @param graceful_shutdown_timeout [integer, Float] the number of seconds to wait until force-shutdown the
|
|
94
97
|
# subscription during the stop process
|
|
98
|
+
# @param in_batches [Boolean] whether a batch of events should be yielded instead a single event
|
|
95
99
|
# @return [void]
|
|
96
100
|
def subscribe(subscription_name, handler:, options: {}, middlewares: nil,
|
|
97
101
|
pull_interval: config.subscription_pull_interval,
|
|
@@ -99,23 +103,78 @@ module PgEventstore
|
|
|
99
103
|
retries_interval: config.subscription_retries_interval,
|
|
100
104
|
restart_terminator: config.subscription_restart_terminator,
|
|
101
105
|
failed_subscription_notifier: config.failed_subscription_notifier,
|
|
102
|
-
graceful_shutdown_timeout: config.subscription_graceful_shutdown_timeout
|
|
106
|
+
graceful_shutdown_timeout: config.subscription_graceful_shutdown_timeout,
|
|
107
|
+
in_batches: false)
|
|
103
108
|
subscription = Subscription.using_connection(config.name).new(
|
|
104
|
-
set: @set_name, name: subscription_name, options
|
|
109
|
+
set: @set_name, name: subscription_name, options:, chunk_query_interval: pull_interval,
|
|
105
110
|
max_restarts_number: max_retries, time_between_restarts: retries_interval
|
|
106
111
|
)
|
|
112
|
+
consumer_class = EventsProcessorConsumer.consumer_class(in_batches)
|
|
107
113
|
runner = SubscriptionRunner.new(
|
|
108
114
|
stats: SubscriptionHandlerPerformance.new,
|
|
109
115
|
events_processor: EventsProcessor.new(
|
|
110
|
-
|
|
111
|
-
|
|
116
|
+
graceful_shutdown_timeout:,
|
|
117
|
+
consumer: consumer_class.create_consumer(handler, deserializer(middlewares)),
|
|
118
|
+
recovery_strategies: recovery_strategies(subscription, restart_terminator, failed_subscription_notifier)
|
|
119
|
+
),
|
|
120
|
+
subscription:
|
|
121
|
+
)
|
|
122
|
+
|
|
123
|
+
@subscriptions_lifecycle.runners.push(runner)
|
|
124
|
+
true
|
|
125
|
+
end
|
|
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),
|
|
112
173
|
recovery_strategies: recovery_strategies(subscription, restart_terminator, failed_subscription_notifier)
|
|
113
174
|
),
|
|
114
|
-
subscription
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
filter_options: options[:filter] || {}
|
|
118
|
-
)
|
|
175
|
+
subscription:,
|
|
176
|
+
max_events_per_chunk: max_events_to_replicate,
|
|
177
|
+
initial_events_per_chunk: max_events_to_replicate
|
|
119
178
|
)
|
|
120
179
|
|
|
121
180
|
@subscriptions_lifecycle.runners.push(runner)
|
|
@@ -156,18 +215,14 @@ module PgEventstore
|
|
|
156
215
|
private
|
|
157
216
|
|
|
158
217
|
# @return [Object] the result of the passed block
|
|
159
|
-
def run_cli_callbacks(&
|
|
218
|
+
def run_cli_callbacks(&)
|
|
160
219
|
return yield unless defined?(::PgEventstore::CLI)
|
|
161
220
|
|
|
162
|
-
PgEventstore::CLI.callbacks.run_callbacks(:start_manager, self, &
|
|
221
|
+
PgEventstore::CLI.callbacks.run_callbacks(:start_manager, self, &)
|
|
163
222
|
end
|
|
164
223
|
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
# @return [Proc]
|
|
168
|
-
def create_raw_event_handler(middlewares, handler)
|
|
169
|
-
deserializer = EventDeserializer.new(select_middlewares(middlewares), config.event_class_resolver)
|
|
170
|
-
->(raw_event) { handler.call(deserializer.deserialize(raw_event)) }
|
|
224
|
+
def deserializer(middlewares)
|
|
225
|
+
EventDeserializer.new(select_middlewares(middlewares), config.event_class_resolver)
|
|
171
226
|
end
|
|
172
227
|
|
|
173
228
|
# @param middlewares [Array, nil]
|
|
@@ -186,9 +241,9 @@ module PgEventstore
|
|
|
186
241
|
[
|
|
187
242
|
RunnerRecoveryStrategies::RestoreConnection.new(config_name),
|
|
188
243
|
RunnerRecoveryStrategies::RestoreSubscriptionRunner.new(
|
|
189
|
-
subscription
|
|
190
|
-
restart_terminator
|
|
191
|
-
failed_subscription_notifier:
|
|
244
|
+
subscription:,
|
|
245
|
+
restart_terminator:,
|
|
246
|
+
failed_subscription_notifier:
|
|
192
247
|
),
|
|
193
248
|
]
|
|
194
249
|
end
|
|
@@ -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
|
|
@@ -2,50 +2,53 @@
|
|
|
2
2
|
|
|
3
3
|
require 'uri'
|
|
4
4
|
|
|
5
|
-
|
|
6
|
-
class
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
5
|
+
module PgEventstore
|
|
6
|
+
class MigrationHelpers
|
|
7
|
+
class << self
|
|
8
|
+
def postgres_uri
|
|
9
|
+
@postgres_uri ||=
|
|
10
|
+
begin
|
|
11
|
+
uri = URI.parse(ENV.fetch('PG_EVENTSTORE_URI'))
|
|
12
|
+
uri.path = '/postgres'
|
|
13
|
+
uri.to_s
|
|
14
|
+
end
|
|
15
|
+
end
|
|
15
16
|
|
|
16
|
-
|
|
17
|
-
|
|
17
|
+
def db_name
|
|
18
|
+
@db_name ||= URI.parse(ENV.fetch('PG_EVENTSTORE_URI')).path&.delete('/')
|
|
19
|
+
end
|
|
18
20
|
end
|
|
19
21
|
end
|
|
20
22
|
end
|
|
21
23
|
|
|
24
|
+
PgEventstore.configure(name: :_postgres_db_connection) do |config|
|
|
25
|
+
config.pg_uri = PgEventstore::MigrationHelpers.postgres_uri
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
PgEventstore.configure(name: :_eventstore_db_connection) do |config|
|
|
29
|
+
config.pg_uri = ENV['PG_EVENTSTORE_URI']
|
|
30
|
+
end
|
|
31
|
+
|
|
22
32
|
namespace :pg_eventstore do
|
|
23
33
|
desc 'Creates events table, indexes, etc.'
|
|
24
34
|
task :create do
|
|
25
|
-
PgEventstore.
|
|
26
|
-
config.pg_uri = helpers.postgres_uri
|
|
27
|
-
end
|
|
28
|
-
|
|
29
|
-
PgEventstore.connection.with do |conn|
|
|
35
|
+
PgEventstore.connection(:_postgres_db_connection).with do |conn|
|
|
30
36
|
exists =
|
|
31
|
-
conn.exec_params('SELECT 1 as exists FROM pg_database where datname = $1', [
|
|
37
|
+
conn.exec_params('SELECT 1 as exists FROM pg_database where datname = $1', [PgEventstore::MigrationHelpers.db_name]).
|
|
32
38
|
first&.dig('exists')
|
|
33
39
|
if exists
|
|
34
|
-
puts "#{
|
|
40
|
+
puts "#{PgEventstore::MigrationHelpers.db_name} already exists. Skipping."
|
|
35
41
|
else
|
|
36
|
-
|
|
42
|
+
escaped_db_name = conn.escape_string(PgEventstore::MigrationHelpers.db_name)
|
|
43
|
+
conn.exec("CREATE DATABASE #{escaped_db_name} WITH OWNER #{conn.escape_string(conn.user)}")
|
|
37
44
|
end
|
|
38
45
|
end
|
|
39
46
|
end
|
|
40
47
|
|
|
41
48
|
task :migrate do
|
|
42
|
-
|
|
43
|
-
config.pg_uri = ENV['PG_EVENTSTORE_URI']
|
|
44
|
-
end
|
|
49
|
+
migration_files_root = File.join(Gem.loaded_specs.fetch('pg_eventstore').gem_dir, 'db/migrations')
|
|
45
50
|
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
PgEventstore.connection.with do |conn|
|
|
51
|
+
PgEventstore.connection(:_eventstore_db_connection).with do |conn|
|
|
49
52
|
conn.exec('CREATE TABLE IF NOT EXISTS migrations (number int NOT NULL)')
|
|
50
53
|
latest_migration =
|
|
51
54
|
conn.exec('SELECT number FROM migrations ORDER BY number DESC LIMIT 1').to_a.dig(0, 'number') || -1
|
|
@@ -56,7 +59,7 @@ namespace :pg_eventstore do
|
|
|
56
59
|
next if latest_migration >= number
|
|
57
60
|
|
|
58
61
|
if File.extname(f_name) == '.rb'
|
|
59
|
-
load
|
|
62
|
+
load(f_name, true)
|
|
60
63
|
else
|
|
61
64
|
conn.exec(File.read(f_name))
|
|
62
65
|
end
|
|
@@ -68,12 +71,8 @@ namespace :pg_eventstore do
|
|
|
68
71
|
|
|
69
72
|
desc 'Drops events table and related pg_eventstore objects.'
|
|
70
73
|
task :drop do
|
|
71
|
-
PgEventstore.
|
|
72
|
-
|
|
73
|
-
end
|
|
74
|
-
|
|
75
|
-
PgEventstore.connection.with do |conn|
|
|
76
|
-
conn.exec("DROP DATABASE IF EXISTS #{conn.escape_string(helpers.db_name)}")
|
|
74
|
+
PgEventstore.connection(:_postgres_db_connection).with do |conn|
|
|
75
|
+
conn.exec("DROP DATABASE IF EXISTS #{conn.escape_string(PgEventstore::MigrationHelpers.db_name)}")
|
|
77
76
|
end
|
|
78
77
|
end
|
|
79
78
|
end
|
data/lib/pg_eventstore/utils.rb
CHANGED
|
@@ -124,6 +124,45 @@ module PgEventstore
|
|
|
124
124
|
|
|
125
125
|
wrapped_exception
|
|
126
126
|
end
|
|
127
|
+
|
|
128
|
+
# Yields the given block and measures its execution time
|
|
129
|
+
# @return [Float] number of seconds the block took to execute
|
|
130
|
+
def benchmark
|
|
131
|
+
start_time = Process.clock_gettime(Process::CLOCK_MONOTONIC)
|
|
132
|
+
yield
|
|
133
|
+
Process.clock_gettime(Process::CLOCK_MONOTONIC) - start_time
|
|
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
|
|
127
166
|
end
|
|
128
167
|
end
|
|
129
168
|
end
|
|
@@ -32,7 +32,7 @@ module PgEventstore
|
|
|
32
32
|
# @return [Array<Hash>, nil]
|
|
33
33
|
# rubocop:disable Style/HashConversion
|
|
34
34
|
def streams_filter
|
|
35
|
-
streams =
|
|
35
|
+
streams = extract_streams_filter(params)
|
|
36
36
|
streams = streams.select { _1 in { context: String, stream_name: String, stream_id: String } }
|
|
37
37
|
streams = streams.map do |stream_attrs|
|
|
38
38
|
Hash[stream_attrs.reject { |_, value| value == '' }].transform_keys(&:to_sym)
|
|
@@ -41,17 +41,32 @@ module PgEventstore
|
|
|
41
41
|
end
|
|
42
42
|
# rubocop:enable Style/HashConversion
|
|
43
43
|
|
|
44
|
-
# @return [String,
|
|
45
|
-
def system_stream
|
|
46
|
-
params in { filter: { system_stream: String => system_stream } }
|
|
47
|
-
system_stream if Stream::KNOWN_SYSTEM_STREAMS.include?(system_stream)
|
|
48
|
-
end
|
|
49
|
-
|
|
50
|
-
# @return [Array<String>, nil]
|
|
44
|
+
# @return [Array<String, Hash>]
|
|
51
45
|
def events_filter
|
|
52
46
|
event_filters = { filter: { event_types: params.dig(:filter, :events) } }
|
|
53
|
-
|
|
54
|
-
|
|
47
|
+
event_types = extract_event_types_filter(event_filters)
|
|
48
|
+
event_types.map do |filter|
|
|
49
|
+
case filter
|
|
50
|
+
when String
|
|
51
|
+
next if filter == ''
|
|
52
|
+
when Hash
|
|
53
|
+
next if filter[:type] == ''
|
|
54
|
+
|
|
55
|
+
filter[:markers] = normalize_markers(filter)
|
|
56
|
+
else
|
|
57
|
+
next
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
filter
|
|
61
|
+
end.compact
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
# @return [Array<String>]
|
|
65
|
+
def markers_filter
|
|
66
|
+
params in { filter: Hash => filter }
|
|
67
|
+
return [] unless filter
|
|
68
|
+
|
|
69
|
+
normalize_markers(filter)
|
|
55
70
|
end
|
|
56
71
|
|
|
57
72
|
# @return [Symbol]
|
|
@@ -87,7 +102,7 @@ module PgEventstore
|
|
|
87
102
|
attrs.transform_values { escape_empty_string(_1) }
|
|
88
103
|
end
|
|
89
104
|
halt 200, {
|
|
90
|
-
results
|
|
105
|
+
results:,
|
|
91
106
|
pagination: { more: !collection.next_page_starting_id.nil?, starting_id: collection.next_page_starting_id },
|
|
92
107
|
}.to_json
|
|
93
108
|
end
|
|
@@ -137,13 +152,55 @@ module PgEventstore
|
|
|
137
152
|
def unescape_empty_string(string)
|
|
138
153
|
string == EMPTY_STRING_SIGN ? '' : string
|
|
139
154
|
end
|
|
155
|
+
|
|
156
|
+
# @param options [Hash]
|
|
157
|
+
# @return [Array<String, Hash>]
|
|
158
|
+
def extract_event_types_filter(options)
|
|
159
|
+
options in { filter: { event_types: Array => event_types } }
|
|
160
|
+
event_types = event_types&.select do |event_type|
|
|
161
|
+
event_type.is_a?(String) || (event_type in { type: String })
|
|
162
|
+
end
|
|
163
|
+
event_types || []
|
|
164
|
+
end
|
|
165
|
+
|
|
166
|
+
# @param options [Hash]
|
|
167
|
+
# @return [Array<Hash[Symbol, String]>]
|
|
168
|
+
def extract_streams_filter(options)
|
|
169
|
+
options in { filter: { streams: Array => streams } }
|
|
170
|
+
streams = streams&.map do |stream_attrs|
|
|
171
|
+
stream_attrs in { context: String | NilClass => context }
|
|
172
|
+
stream_attrs in { stream_name: String | NilClass => stream_name }
|
|
173
|
+
stream_attrs in { stream_id: String | NilClass => stream_id }
|
|
174
|
+
{ context:, stream_name:, stream_id: }
|
|
175
|
+
end
|
|
176
|
+
streams || []
|
|
177
|
+
end
|
|
178
|
+
|
|
179
|
+
private
|
|
180
|
+
|
|
181
|
+
# @param hash [Hash]
|
|
182
|
+
# @return [Array<String>]
|
|
183
|
+
def normalize_markers(hash)
|
|
184
|
+
hash in { markers: Array => markers }
|
|
185
|
+
markers ||= []
|
|
186
|
+
markers.grep(String).reject { _1 == '' }
|
|
187
|
+
end
|
|
140
188
|
end
|
|
141
189
|
|
|
142
190
|
get '/' do
|
|
143
191
|
streams_filter = self.streams_filter&.map do |attrs|
|
|
144
192
|
attrs.transform_values { unescape_empty_string(_1) }
|
|
145
193
|
end
|
|
146
|
-
events_filter = self.events_filter
|
|
194
|
+
events_filter = self.events_filter.map do |event_type|
|
|
195
|
+
next unescape_empty_string(event_type) if event_type.is_a?(String)
|
|
196
|
+
|
|
197
|
+
event_type[:type] = unescape_empty_string(event_type[:type])
|
|
198
|
+
event_type[:markers] = event_type[:markers]&.grep(String) || []
|
|
199
|
+
event_type
|
|
200
|
+
end
|
|
201
|
+
markers_filter = self.markers_filter.map(&method(:unescape_empty_string))
|
|
202
|
+
events_filter.push({ markers: markers_filter }) if markers_filter.any?
|
|
203
|
+
|
|
147
204
|
@collection = Paginator::EventsCollection.new(
|
|
148
205
|
current_config,
|
|
149
206
|
starting_id: params[:starting_id]&.to_i,
|
|
@@ -152,14 +209,20 @@ module PgEventstore
|
|
|
152
209
|
options: {
|
|
153
210
|
filter: { event_types: events_filter, streams: streams_filter },
|
|
154
211
|
resolve_link_tos: resolve_link_tos?,
|
|
155
|
-
}
|
|
156
|
-
system_stream: system_stream
|
|
212
|
+
}
|
|
157
213
|
)
|
|
214
|
+
@gp_to_sp_map = EventSubscriptionPositionQueries.new(
|
|
215
|
+
PgEventstore.connection(current_config)
|
|
216
|
+
).subscription_positions_from_db(@collection.collection)
|
|
158
217
|
|
|
159
218
|
if request.xhr?
|
|
160
219
|
content_type 'application/json'
|
|
161
220
|
halt 200, {
|
|
162
|
-
events: erb(
|
|
221
|
+
events: erb(
|
|
222
|
+
:'home/partials/events',
|
|
223
|
+
{ layout: false },
|
|
224
|
+
{ events: @collection.collection, gp_to_sp_map: @gp_to_sp_map }
|
|
225
|
+
),
|
|
163
226
|
total_count: total_count(@collection.total_count),
|
|
164
227
|
pagination: erb(:'home/partials/pagination_links', { layout: false }, { collection: @collection }),
|
|
165
228
|
}.to_json
|
|
@@ -168,6 +231,16 @@ module PgEventstore
|
|
|
168
231
|
end
|
|
169
232
|
end
|
|
170
233
|
|
|
234
|
+
get '/streams' do
|
|
235
|
+
@collection = Paginator::StreamsCollection.new(
|
|
236
|
+
current_config,
|
|
237
|
+
starting_id: params[:starting_id]&.to_i,
|
|
238
|
+
per_page: Paginator::StreamsCollection::PER_PAGE[params[:per_page]],
|
|
239
|
+
order: Paginator::StreamsCollection::SQL_DIRECTIONS[params[:order]]
|
|
240
|
+
)
|
|
241
|
+
erb :'streams/index'
|
|
242
|
+
end
|
|
243
|
+
|
|
171
244
|
get '/subscriptions' do
|
|
172
245
|
@set_collection = Subscriptions::SetCollection.new(connection)
|
|
173
246
|
@current_set = params[:set_name] || @set_collection.names.first
|
|
@@ -188,8 +261,8 @@ module PgEventstore
|
|
|
188
261
|
connection, @current_set, state: params[:state]
|
|
189
262
|
).subscriptions
|
|
190
263
|
@association = Subscriptions::SubscriptionsToSetAssociation.new(
|
|
191
|
-
subscriptions_set
|
|
192
|
-
subscriptions:
|
|
264
|
+
subscriptions_set:,
|
|
265
|
+
subscriptions:
|
|
193
266
|
)
|
|
194
267
|
erb :'subscriptions/index'
|
|
195
268
|
end
|
|
@@ -247,6 +320,17 @@ module PgEventstore
|
|
|
247
320
|
paginated_json_response(collection)
|
|
248
321
|
end
|
|
249
322
|
|
|
323
|
+
get '/markers_filtering', provides: :json do
|
|
324
|
+
collection = Paginator::MarkersCollection.new(
|
|
325
|
+
current_config,
|
|
326
|
+
starting_id: unescape_empty_string(params[:starting_id]),
|
|
327
|
+
per_page: Paginator::MarkersCollection::PER_PAGE,
|
|
328
|
+
order: :asc,
|
|
329
|
+
options: { query: params[:term] }
|
|
330
|
+
)
|
|
331
|
+
paginated_json_response(collection)
|
|
332
|
+
end
|
|
333
|
+
|
|
250
334
|
post '/subscription_cmd/:set_id/:id/:cmd' do
|
|
251
335
|
validate_subscription_cmd(params[:cmd])
|
|
252
336
|
cmd_class = SubscriptionRunnerCommands.command_class(params[:cmd])
|
|
@@ -279,14 +363,14 @@ module PgEventstore
|
|
|
279
363
|
end
|
|
280
364
|
|
|
281
365
|
post '/delete_subscription/:id' do
|
|
282
|
-
SubscriptionQueries.new(connection).delete(Integer(params[:id]))
|
|
366
|
+
SubscriptionQueries.new(connection, QueryStrategy::Foreground.new(connection)).delete(Integer(params[:id]))
|
|
283
367
|
|
|
284
368
|
redirect redirect_back_url(fallback_url: url('/subscriptions'))
|
|
285
369
|
end
|
|
286
370
|
|
|
287
371
|
post '/delete_all_subscriptions' do
|
|
288
372
|
params[:ids].each do |id|
|
|
289
|
-
SubscriptionQueries.new(connection).delete(Integer(id))
|
|
373
|
+
SubscriptionQueries.new(connection, QueryStrategy::Foreground.new(connection)).delete(Integer(id))
|
|
290
374
|
end
|
|
291
375
|
|
|
292
376
|
redirect redirect_back_url(fallback_url: url('/subscriptions'))
|
|
@@ -301,7 +385,7 @@ module PgEventstore
|
|
|
301
385
|
).first
|
|
302
386
|
if event&.global_position == global_position
|
|
303
387
|
begin
|
|
304
|
-
PgEventstore.maintenance(current_config).delete_event(event, force:
|
|
388
|
+
PgEventstore.maintenance(current_config).delete_event(event, force:)
|
|
305
389
|
self.flash_message = {
|
|
306
390
|
message: "An event at global position #{event.global_position} has been deleted successfully.",
|
|
307
391
|
kind: 'success',
|
|
@@ -4,6 +4,9 @@ module PgEventstore
|
|
|
4
4
|
module Web
|
|
5
5
|
module Paginator
|
|
6
6
|
class BaseCollection
|
|
7
|
+
# This is the minimum amount of symbols requeried to perform search using trigrams gin index
|
|
8
|
+
MIN_QUERY_SIZE_FOR_ADVANCE_SEARCH = 3
|
|
9
|
+
|
|
7
10
|
# @!attribute config_name
|
|
8
11
|
# @return [Symbol]
|
|
9
12
|
attr_reader :config_name
|
|
@@ -30,7 +33,8 @@ module PgEventstore
|
|
|
30
33
|
@starting_id = starting_id
|
|
31
34
|
@per_page = per_page
|
|
32
35
|
@order = order
|
|
33
|
-
@options =
|
|
36
|
+
@options =
|
|
37
|
+
options.is_a?(Sinatra::IndifferentHash) ? Utils.deep_transform_keys(Hash[options], &:to_sym) : options
|
|
34
38
|
end
|
|
35
39
|
|
|
36
40
|
# @return [Array]
|
|
@@ -12,9 +12,9 @@ module PgEventstore
|
|
|
12
12
|
@collection ||=
|
|
13
13
|
begin
|
|
14
14
|
sql_builder = SQLBuilder.new.select('event_type').from('partitions')
|
|
15
|
-
sql_builder.where('
|
|
15
|
+
sql_builder.where('event_type is not null')
|
|
16
16
|
sql_builder.where("event_type #{direction_operator} ?", starting_id) if starting_id
|
|
17
|
-
sql_builder
|
|
17
|
+
compute_event_type_filter(sql_builder)
|
|
18
18
|
sql_builder.group('event_type').order("event_type #{order}").limit(per_page)
|
|
19
19
|
connection.with do |conn|
|
|
20
20
|
conn.exec_params(*sql_builder.to_exec_params)
|
|
@@ -28,9 +28,8 @@ module PgEventstore
|
|
|
28
28
|
|
|
29
29
|
starting_id = collection.first['event_type']
|
|
30
30
|
sql_builder = SQLBuilder.new.select('event_type').from('partitions')
|
|
31
|
-
sql_builder.where('context is not null and stream_name is not null')
|
|
32
31
|
sql_builder.where("event_type #{direction_operator} ?", starting_id)
|
|
33
|
-
sql_builder
|
|
32
|
+
compute_event_type_filter(sql_builder)
|
|
34
33
|
sql_builder.group('event_type').order("event_type #{order}").limit(1).offset(per_page)
|
|
35
34
|
|
|
36
35
|
connection.with do |conn|
|
|
@@ -44,6 +43,17 @@ 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_event_type_filter(builder)
|
|
50
|
+
query = options[:query].to_s
|
|
51
|
+
if query.size < MIN_QUERY_SIZE_FOR_ADVANCE_SEARCH
|
|
52
|
+
builder.where('event_type like ?', "#{query}%")
|
|
53
|
+
else
|
|
54
|
+
builder.where('event_type ilike ?', "%#{query}%")
|
|
55
|
+
end
|
|
56
|
+
end
|
|
47
57
|
end
|
|
48
58
|
end
|
|
49
59
|
end
|