pg_eventstore 2.0.0 → 3.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.rubocop.yml +10 -1
- data/CHANGELOG.md +186 -20
- data/README.md +25 -15
- data/db/migrations/10_setup_pg_cron.rb +1 -23
- 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/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 +17 -8
- 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/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/client.rb +163 -50
- 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 +9 -7
- data/lib/pg_eventstore/commands/event_modifiers/prepare_regular_event.rb +12 -7
- data/lib/pg_eventstore/commands/link_to.rb +5 -5
- 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 +21 -2
- data/lib/pg_eventstore/errors.rb +136 -10
- data/lib/pg_eventstore/event.rb +34 -2
- 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 +2 -2
- 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 +7 -93
- 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 +4 -4
- data/lib/pg_eventstore/queries/maintenance_queries.rb +159 -42
- data/lib/pg_eventstore/queries/partition_queries.rb +45 -103
- 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 +52 -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 +13 -16
- data/lib/pg_eventstore/stream_global_index.rb +28 -0
- 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 +12 -0
- data/lib/pg_eventstore/subscriptions/callback_handlers/subscription_runner_handlers.rb +21 -7
- data/lib/pg_eventstore/subscriptions/events_processor.rb +20 -18
- 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_queries.rb +78 -54
- 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 +2 -1
- 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 +24 -0
- data/lib/pg_eventstore/subscriptions/subscription_handler_performance.rb +4 -2
- data/lib/pg_eventstore/subscriptions/subscription_runner.rb +20 -9
- data/lib/pg_eventstore/subscriptions/subscription_runner_commands/reset_position.rb +1 -1
- data/lib/pg_eventstore/subscriptions/subscription_runners_feeder.rb +9 -18
- data/lib/pg_eventstore/subscriptions/subscriptions_lifecycle.rb +0 -12
- data/lib/pg_eventstore/subscriptions/subscriptions_manager.rb +74 -14
- data/lib/pg_eventstore/{subscriptions/synchronized_array.rb → synchronized_array.rb} +15 -0
- data/lib/pg_eventstore/tasks/setup.rake +2 -2
- data/lib/pg_eventstore/utils.rb +31 -0
- data/lib/pg_eventstore/version.rb +1 -1
- data/lib/pg_eventstore/web/application.rb +100 -16
- 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 +16 -9
- 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/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 +23 -60
- 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 +40 -42
- 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/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 +16 -2
- 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/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 +4 -36
- 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 +5 -9
- 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 +2 -0
- 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 +17 -6
- 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 +7 -39
- 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 -2
- data/sig/pg_eventstore/subscriptions/subscription_runners_feeder.rbs +1 -8
- 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 +10 -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 +175 -20
- data/Dockerfile +0 -3
- 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/subscription_service_queries.rb +0 -78
- 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/subscription_service_queries.rbs +0 -19
- data/sig/pg_eventstore/subscriptions/synchronized_array.rbs +0 -4
- /data/sig/interfaces/{_raw_event_handler.rbs → raw_event_handler.rbs} +0 -0
|
@@ -0,0 +1,179 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module PgEventstore
|
|
4
|
+
class IndexFilteringQueries
|
|
5
|
+
# @!attribute connection
|
|
6
|
+
# @return [PgEventstore::Connection]
|
|
7
|
+
attr_reader :connection
|
|
8
|
+
private :connection
|
|
9
|
+
|
|
10
|
+
# @param connection [PgEventstore::Connection]
|
|
11
|
+
# @param query_strategy [PgEventstore::QueryStrategy]
|
|
12
|
+
def initialize(connection, query_strategy)
|
|
13
|
+
@connection = connection
|
|
14
|
+
@query_strategy = query_strategy
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
# @param stream [PgEventstore::Stream]
|
|
18
|
+
# @param expected_revisions [Array<PgEventstore::Commands::RevisionCheck::ExpectedRevision::EventTypeRevision,
|
|
19
|
+
# PgEventstore::Commands::RevisionCheck::ExpectedRevision::EventTypeRevisionWithMarkers,
|
|
20
|
+
# PgEventstore::Commands::RevisionCheck::ExpectedRevision::MarkersRevision>]
|
|
21
|
+
# @return [Array<PgEventstore::EventGlobalIndex::RevisionCheckRepr>]
|
|
22
|
+
def fetch_indexes_for_revision_validation(stream, expected_revisions)
|
|
23
|
+
builders = expected_revisions.map do |expected_revision|
|
|
24
|
+
case expected_revision
|
|
25
|
+
when Commands::RevisionCheck::ExpectedRevision::EventTypeRevision
|
|
26
|
+
QueryBuilders::IndexBasedEventsFiltering.sql_builder_for_event_type_revision_validation(
|
|
27
|
+
stream, expected_revision
|
|
28
|
+
)
|
|
29
|
+
when Commands::RevisionCheck::ExpectedRevision::EventTypeRevisionWithMarkers
|
|
30
|
+
QueryBuilders::IndexBasedEventsFiltering.sql_builder_for_event_type_with_markers_revision_validation(
|
|
31
|
+
stream, expected_revision
|
|
32
|
+
)
|
|
33
|
+
when Commands::RevisionCheck::ExpectedRevision::MarkersRevision
|
|
34
|
+
QueryBuilders::IndexBasedEventsFiltering.sql_builder_for_markers_revision_validation(
|
|
35
|
+
stream, expected_revision
|
|
36
|
+
)
|
|
37
|
+
else
|
|
38
|
+
Utils.missing_implementation!(expected_revision)
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
final = SQLBuilder.union_builders(builders)
|
|
42
|
+
deserialize(@query_strategy.exec_params(*final.to_exec_params), repr: EventGlobalIndex::ReprType::REVISION_CHECK)
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
# @param filters_collection [PgEventstore::QueryBuilders::Filters::Collection]
|
|
46
|
+
# @param cursor [PgEventstore::QueryBuilders::ReadCursor::StreamCursor]
|
|
47
|
+
# @return [Array<PgEventstore::EventGlobalIndex::ReadApiRepr>]
|
|
48
|
+
def fetch_indexes_for_read_api(filters_collection, cursor)
|
|
49
|
+
filter_rows =
|
|
50
|
+
if filters_collection.collection.any?(&:ambiguous_event_type?)
|
|
51
|
+
expand_event_types(filters_collection)
|
|
52
|
+
else
|
|
53
|
+
filters_collection.collection
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
sql_builder = QueryBuilders::IndexBasedEventsFiltering.sql_builder_for_read_common(filter_rows, cursor)
|
|
57
|
+
deserialize(@query_strategy.exec_params(*sql_builder.to_exec_params), repr: EventGlobalIndex::ReprType::READ_API)
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
# @param filters_collection [PgEventstore::QueryBuilders::Filters::Collection]
|
|
61
|
+
# @param cursor [PgEventstore::QueryBuilders::ReadCursor::StreamCursor]
|
|
62
|
+
# @return [Array<PgEventstore::EventGlobalIndex::ReadApiRepr>]
|
|
63
|
+
def fetch_grouped_indexes_for_read_api(filters_collection, cursor)
|
|
64
|
+
filter_rows =
|
|
65
|
+
if filters_collection.collection.any?(&:ambiguous_event_type?)
|
|
66
|
+
expand_event_types(filters_collection)
|
|
67
|
+
else
|
|
68
|
+
filters_collection.collection
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
sql_builder = QueryBuilders::IndexBasedEventsFiltering.sql_builder_for_read_grouped(filter_rows, cursor)
|
|
72
|
+
deserialize(@query_strategy.exec_params(*sql_builder.to_exec_params), repr: EventGlobalIndex::ReprType::READ_API)
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
# @param indexes [Array<PgEventstore::EventGlobalIndex::ReadApiRepr>]
|
|
76
|
+
# @param resolve_link_tos [Boolean]
|
|
77
|
+
# @return [PgEventstore::Chunks::Repository]
|
|
78
|
+
def compute_read_api_chunks_repo(indexes, resolve_link_tos)
|
|
79
|
+
repo = Chunks::Repository.new
|
|
80
|
+
repo.add_chunk(Chunks::ReadApiEventsIndexChunk.new(indexes, connection, @query_strategy, resolve_link_tos))
|
|
81
|
+
repo
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
private
|
|
85
|
+
|
|
86
|
+
# @return [PgEventstore::PartitionQueries]
|
|
87
|
+
def partition_queries
|
|
88
|
+
PartitionQueries.new(connection)
|
|
89
|
+
end
|
|
90
|
+
|
|
91
|
+
# @param filters_collection [PgEventstore::QueryBuilders::Filters::Collection]
|
|
92
|
+
# @return [Array<PgEventstore::QueryBuilders::Filters::FilterRow>]
|
|
93
|
+
def expand_event_types(filters_collection)
|
|
94
|
+
filter_rows = filters_collection.collection
|
|
95
|
+
to_expand = filter_rows.select(&:ambiguous_event_type?)
|
|
96
|
+
rest_filter_rows = filter_rows - to_expand
|
|
97
|
+
partition_builders = to_expand.map do |filter_row|
|
|
98
|
+
partitions_filtering = QueryBuilders::PartitionsFiltering.new
|
|
99
|
+
partitions_filtering.with_event_types
|
|
100
|
+
filter_row = filter_row.to_filter_row if filter_row.is_a?(QueryBuilders::Filters::MarkerFilterRow)
|
|
101
|
+
partitions_filtering.add_filter_row(filter_row)
|
|
102
|
+
partitions_filtering.to_sql_builder.unselect.select('context, stream_name, event_type')
|
|
103
|
+
end
|
|
104
|
+
final_partition_builder = SQLBuilder.union_builders(partition_builders)
|
|
105
|
+
expanded_partitions_list = @query_strategy.exec_params(*final_partition_builder.to_exec_params)
|
|
106
|
+
expanded_partitions_list = expanded_partitions_list.group_by { _1['event_type'] }
|
|
107
|
+
expanded_filter_rows =
|
|
108
|
+
to_expand.flat_map do |filter_row|
|
|
109
|
+
case filter_row
|
|
110
|
+
when QueryBuilders::Filters::FilterRow
|
|
111
|
+
filter_row.event_type_filters.flat_map do |event_type_filter|
|
|
112
|
+
related_partitions =
|
|
113
|
+
if event_type_filter.prefix?
|
|
114
|
+
expanded_partitions_list.select do |event_type, _|
|
|
115
|
+
event_type.start_with?(event_type_filter.event_type)
|
|
116
|
+
end.values.flatten
|
|
117
|
+
else
|
|
118
|
+
expanded_partitions_list[event_type_filter.event_type]
|
|
119
|
+
end
|
|
120
|
+
next [] unless related_partitions
|
|
121
|
+
|
|
122
|
+
if filter_row.stream_filter
|
|
123
|
+
related_partitions = related_partitions.select do |attrs|
|
|
124
|
+
if filter_row.stream_filter.context?
|
|
125
|
+
attrs['context'] == filter_row.stream_filter.context
|
|
126
|
+
else
|
|
127
|
+
attrs['context'] == filter_row.stream_filter.context &&
|
|
128
|
+
attrs['stream_name'] == filter_row.stream_filter.stream_name
|
|
129
|
+
end
|
|
130
|
+
end
|
|
131
|
+
end
|
|
132
|
+
related_partitions.map do |partition_attrs|
|
|
133
|
+
stream_filter = QueryBuilders::Filters::StreamFilter.new(
|
|
134
|
+
context: partition_attrs['context'],
|
|
135
|
+
stream_name: partition_attrs['stream_name']
|
|
136
|
+
)
|
|
137
|
+
event_type_filter = QueryBuilders::Filters::EventTypeFilter.new(
|
|
138
|
+
event_type: partition_attrs['event_type'], prefix: false
|
|
139
|
+
)
|
|
140
|
+
QueryBuilders::Filters::FilterRow.new(stream_filter:, event_type_filters: [event_type_filter])
|
|
141
|
+
end
|
|
142
|
+
end
|
|
143
|
+
when QueryBuilders::Filters::MarkerFilterRow
|
|
144
|
+
related_partitions = expanded_partitions_list[filter_row.marker_filter.event_type]
|
|
145
|
+
next [] unless related_partitions
|
|
146
|
+
|
|
147
|
+
if filter_row.stream_filter
|
|
148
|
+
related_partitions = related_partitions.select do |attrs|
|
|
149
|
+
attrs['context'] == filter_row.stream_filter.context
|
|
150
|
+
end
|
|
151
|
+
end
|
|
152
|
+
related_partitions.map do |partition_attrs|
|
|
153
|
+
stream_filter = QueryBuilders::Filters::StreamFilter.new(
|
|
154
|
+
context: partition_attrs['context'],
|
|
155
|
+
stream_name: partition_attrs['stream_name']
|
|
156
|
+
)
|
|
157
|
+
QueryBuilders::Filters::MarkerFilterRow.new(stream_filter:, marker_filter: filter_row.marker_filter.dup)
|
|
158
|
+
end
|
|
159
|
+
else
|
|
160
|
+
Utils.missing_implementation!(filter_row)
|
|
161
|
+
end
|
|
162
|
+
end
|
|
163
|
+
adjusted_rows = expanded_filter_rows + rest_filter_rows
|
|
164
|
+
return [QueryBuilders::Filters::FilterRow.null_filter_row] if adjusted_rows.empty?
|
|
165
|
+
|
|
166
|
+
adjusted_rows
|
|
167
|
+
end
|
|
168
|
+
|
|
169
|
+
# @param repr [Symbol, nil]
|
|
170
|
+
# @return [Array<PgEventstore::EventGlobalIndex>, Array<PgEventstore::EventGlobalIndex::SubscriptionRepr>,
|
|
171
|
+
# Array<PgEventstore::EventGlobalIndex::ReadApiRepr>, Array<PgEventstore::EventGlobalIndex::WriteApiRepr>,
|
|
172
|
+
# Array<PgEventstore::EventGlobalIndex::RevisionCheckRepr>]
|
|
173
|
+
def deserialize(pg_result, repr: nil)
|
|
174
|
+
pg_result.map do |attrs|
|
|
175
|
+
EventGlobalIndex.create_representation(attrs.transform_keys(&:to_sym), repr:)
|
|
176
|
+
end
|
|
177
|
+
end
|
|
178
|
+
end
|
|
179
|
+
end
|
|
@@ -9,8 +9,10 @@ module PgEventstore
|
|
|
9
9
|
private :connection
|
|
10
10
|
|
|
11
11
|
# @param connection [PgEventstore::Connection]
|
|
12
|
-
|
|
12
|
+
# @param query_strategy [PgEventstore::QueryStrategy]
|
|
13
|
+
def initialize(connection, query_strategy)
|
|
13
14
|
@connection = connection
|
|
15
|
+
@query_strategy = query_strategy
|
|
14
16
|
end
|
|
15
17
|
|
|
16
18
|
# Takes an array of events, look for link events in there and replaces link events with original events
|
|
@@ -46,9 +48,7 @@ module PgEventstore
|
|
|
46
48
|
top_builder.union(builder)
|
|
47
49
|
end
|
|
48
50
|
|
|
49
|
-
|
|
50
|
-
conn.exec_params(*sql_builder.to_exec_params)
|
|
51
|
-
end.to_a
|
|
51
|
+
@query_strategy.exec_params(*sql_builder.to_exec_params).to_a
|
|
52
52
|
end
|
|
53
53
|
|
|
54
54
|
# @return [PgEventstore::PartitionQueries]
|
|
@@ -3,6 +3,11 @@
|
|
|
3
3
|
module PgEventstore
|
|
4
4
|
# @!visibility private
|
|
5
5
|
class MaintenanceQueries
|
|
6
|
+
# @return [Integer]
|
|
7
|
+
EVENT_INDEXES_TO_REMOVE_PER_QUERY = 10_000
|
|
8
|
+
# @return [Integer]
|
|
9
|
+
EVENT_INDEXES_TO_UPDATE_PER_QUERY = 10_000
|
|
10
|
+
|
|
6
11
|
# @!attribute connection
|
|
7
12
|
# @return [PgEventstore::Connection]
|
|
8
13
|
attr_reader :connection
|
|
@@ -13,36 +18,155 @@ module PgEventstore
|
|
|
13
18
|
@connection = connection
|
|
14
19
|
end
|
|
15
20
|
|
|
21
|
+
# TODO: refactor me. Reason: fatty
|
|
16
22
|
# @param stream [PgEventstore::Stream]
|
|
17
23
|
# @return [Integer] number of deleted events of the given stream
|
|
18
24
|
def delete_stream(stream)
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
25
|
+
total_removed = 0
|
|
26
|
+
transaction_queries.transaction(:read_committed) do
|
|
27
|
+
stream_global_idx = streams_global_index_queries.find_by!(stream)
|
|
28
|
+
streams_global_index_queries.delete(stream_global_idx.id)
|
|
29
|
+
global_position = 1
|
|
30
|
+
loop do
|
|
31
|
+
deleted_events_global_index = connection.with do |conn|
|
|
32
|
+
conn.exec_params(<<~SQL, [stream_global_idx.id, global_position, EVENT_INDEXES_TO_REMOVE_PER_QUERY]).to_a
|
|
33
|
+
delete from events_global_index
|
|
34
|
+
where global_position in (
|
|
35
|
+
select global_position from events_global_index
|
|
36
|
+
where streams_global_index_id = $1 and global_position >= $2
|
|
37
|
+
order by global_position asc
|
|
38
|
+
limit $3
|
|
39
|
+
)
|
|
40
|
+
returning event_type_partition_id, global_position
|
|
41
|
+
SQL
|
|
42
|
+
end
|
|
43
|
+
break if deleted_events_global_index.empty?
|
|
44
|
+
|
|
45
|
+
global_position = deleted_events_global_index.last['global_position'] + 1
|
|
46
|
+
total_removed += deleted_events_global_index.size
|
|
47
|
+
deleted_events_global_index = deleted_events_global_index.group_by { _1['event_type_partition_id'] }
|
|
48
|
+
partitions = partition_queries.find_by_ids(deleted_events_global_index.keys).to_h { [_1['id'], _1] }
|
|
49
|
+
queries = deleted_events_global_index.map do |partition_id, idxs|
|
|
50
|
+
partition = partitions[partition_id]
|
|
51
|
+
positions = idxs.map { _1['global_position'] }.join(', ')
|
|
52
|
+
context = PG::Connection.escape(partition['context'])
|
|
53
|
+
stream_name = PG::Connection.escape(partition['stream_name'])
|
|
54
|
+
event_type = PG::Connection.escape(partition['event_type'])
|
|
55
|
+
<<~SQL
|
|
56
|
+
delete from events
|
|
57
|
+
where context = '#{context}' and stream_name = '#{stream_name}' and type = '#{event_type}'
|
|
58
|
+
and global_position in (#{positions});
|
|
59
|
+
delete from event_subscription_positions where global_position in (#{positions});
|
|
60
|
+
delete from event_subscription_positions_unprocessed where global_position in (#{positions});
|
|
61
|
+
delete from event_markers_index where global_position in (#{positions});
|
|
62
|
+
SQL
|
|
63
|
+
end
|
|
64
|
+
connection.with do |conn|
|
|
65
|
+
conn.exec(queries.join("\n"))
|
|
66
|
+
end
|
|
67
|
+
end
|
|
68
|
+
end
|
|
69
|
+
total_removed
|
|
24
70
|
end
|
|
25
71
|
|
|
72
|
+
# TODO: refactor me. Reason: fatty
|
|
26
73
|
# @param event [PgEventstore::Event]
|
|
27
|
-
# @return [
|
|
74
|
+
# @return [void]
|
|
28
75
|
def delete_event(event)
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
76
|
+
stream = event.stream
|
|
77
|
+
transaction_queries.transaction(:read_commited) do
|
|
78
|
+
stream_global_idx = streams_global_index_queries.find_by!(stream)
|
|
79
|
+
current_stream_revision = connection.with do |conn|
|
|
80
|
+
conn.exec_params(
|
|
81
|
+
'select stream_revision from streams_global_index where id = $1 for update', [stream_global_idx.id]
|
|
82
|
+
)
|
|
83
|
+
end.to_a.first['stream_revision']
|
|
84
|
+
exists =
|
|
85
|
+
connection.with do |conn|
|
|
86
|
+
conn.exec_params(<<~SQL, [event.global_position]).first&.[]('one') == 1
|
|
87
|
+
select 1 as one from events_global_index where global_position = $1
|
|
88
|
+
SQL
|
|
89
|
+
end
|
|
90
|
+
raise RecordNotFound.new('events_global_index', event.global_position) unless exists
|
|
91
|
+
# We are deleting the only event. Thus, we should delete the whole stream
|
|
92
|
+
return delete_stream(stream) if current_stream_revision == 0
|
|
35
93
|
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
94
|
+
deleted_event = connection.with do |conn|
|
|
95
|
+
conn.exec_params(<<~SQL, [stream_global_idx.id, event.global_position]).to_a.first
|
|
96
|
+
delete from events_global_index where streams_global_index_id = $1 and global_position = $2
|
|
97
|
+
returning global_position, event_type_partition_id, stream_revision
|
|
98
|
+
SQL
|
|
99
|
+
end
|
|
100
|
+
|
|
101
|
+
affected_partition = partition_queries.find_by_ids([deleted_event['event_type_partition_id']]).first
|
|
102
|
+
connection.with do |conn|
|
|
103
|
+
delete_args = [
|
|
104
|
+
affected_partition['context'],
|
|
105
|
+
affected_partition['stream_name'],
|
|
106
|
+
affected_partition['event_type'],
|
|
107
|
+
deleted_event['global_position'],
|
|
108
|
+
]
|
|
109
|
+
conn.exec_params(<<~SQL, delete_args)
|
|
110
|
+
with _1 as (delete from events where context = $1 and stream_name = $2 and type = $3 and global_position = $4),
|
|
111
|
+
_2 as (delete from event_subscription_positions where global_position = $4),
|
|
112
|
+
_3 as (delete from event_subscription_positions_unprocessed where global_position = $4),
|
|
113
|
+
_4 as (delete from event_markers_index where global_position = $4)
|
|
114
|
+
select 1;
|
|
115
|
+
SQL
|
|
116
|
+
end
|
|
117
|
+
first_updated_event = nil
|
|
118
|
+
stream_revision = deleted_event['stream_revision']
|
|
119
|
+
loop do
|
|
120
|
+
updated_events = connection.with do |conn|
|
|
121
|
+
conn.exec_params(<<~SQL, [stream_global_idx.id, stream_revision, EVENT_INDEXES_TO_UPDATE_PER_QUERY]).to_a
|
|
122
|
+
update event_markers_index set stream_revision = stream_revision - 1
|
|
123
|
+
where global_position in (
|
|
124
|
+
select global_position from events_global_index
|
|
125
|
+
where streams_global_index_id = $1 and stream_revision > $2
|
|
126
|
+
order by stream_revision asc
|
|
127
|
+
limit $3
|
|
128
|
+
)
|
|
129
|
+
SQL
|
|
130
|
+
conn.exec_params(<<~SQL, [stream_global_idx.id, stream_revision, EVENT_INDEXES_TO_UPDATE_PER_QUERY]).to_a
|
|
131
|
+
update events_global_index set stream_revision = stream_revision - 1
|
|
132
|
+
where global_position in (
|
|
133
|
+
select global_position from events_global_index
|
|
134
|
+
where streams_global_index_id = $1 and stream_revision > $2
|
|
135
|
+
order by stream_revision asc
|
|
136
|
+
limit $3
|
|
137
|
+
)
|
|
138
|
+
returning event_type_partition_id, global_position, stream_revision
|
|
139
|
+
SQL
|
|
140
|
+
end
|
|
141
|
+
first_updated_event ||= updated_events.min_by { _1['stream_revision'] }
|
|
142
|
+
break if updated_events.empty?
|
|
143
|
+
|
|
144
|
+
stream_revision += updated_events.size
|
|
145
|
+
updated_events = updated_events.group_by { _1['event_type_partition_id'] }
|
|
146
|
+
partitions = partition_queries.find_by_ids(updated_events.keys).to_h { [_1['id'], _1] }
|
|
147
|
+
queries = updated_events.flat_map do |partition_id, idxs|
|
|
148
|
+
partition = partitions[partition_id]
|
|
149
|
+
context = PG::Connection.escape(partition['context'])
|
|
150
|
+
stream_name = PG::Connection.escape(partition['stream_name'])
|
|
151
|
+
event_type = PG::Connection.escape(partition['event_type'])
|
|
152
|
+
idxs.map do |idx|
|
|
153
|
+
<<~SQL
|
|
154
|
+
update events set stream_revision = #{idx['stream_revision']}
|
|
155
|
+
where context = '#{context}' and stream_name = '#{stream_name}' and type = '#{event_type}' and
|
|
156
|
+
global_position = #{idx['global_position']};
|
|
157
|
+
SQL
|
|
158
|
+
end
|
|
159
|
+
end
|
|
160
|
+
connection.with do |conn|
|
|
161
|
+
conn.exec(queries.join("\n"))
|
|
162
|
+
end
|
|
163
|
+
end
|
|
164
|
+
stream_idx_attrs_to_update = { stream_revision: current_stream_revision - 1 }
|
|
165
|
+
# Adjust starting_position in case zero revision event was deleted
|
|
166
|
+
if deleted_event['stream_revision'] == 0
|
|
167
|
+
stream_idx_attrs_to_update[:starting_position] = first_updated_event['global_position']
|
|
168
|
+
end
|
|
169
|
+
streams_global_index_queries.update(stream_global_idx.id, **stream_idx_attrs_to_update)
|
|
46
170
|
end
|
|
47
171
|
end
|
|
48
172
|
|
|
@@ -50,32 +174,25 @@ module PgEventstore
|
|
|
50
174
|
# @param after_revision [Integer]
|
|
51
175
|
# @return [Integer]
|
|
52
176
|
def events_to_lock_count(stream, after_revision)
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
EXPLAIN SELECT * FROM events
|
|
56
|
-
WHERE context = $1 AND stream_name = $2 AND stream_id = $3 AND stream_revision > $4
|
|
57
|
-
SQL
|
|
58
|
-
end.to_a.first['QUERY PLAN'].match(/rows=(\d+)/)[1].to_i
|
|
177
|
+
stream_index = streams_global_index_queries.find_by!(stream)
|
|
178
|
+
stream_index.stream_revision - after_revision
|
|
59
179
|
end
|
|
60
180
|
|
|
61
|
-
|
|
62
|
-
# @return [PgEventstore::Event]
|
|
63
|
-
def reload_event(event)
|
|
64
|
-
event_attrs = connection.with do |conn|
|
|
65
|
-
conn.exec_params(<<~SQL, [event.stream&.context, event.stream&.stream_name, event.type, event.global_position])
|
|
66
|
-
SELECT * FROM events WHERE context = $1 AND stream_name = $2 AND type = $3 AND global_position = $4 LIMIT 1
|
|
67
|
-
SQL
|
|
68
|
-
end.to_a.first
|
|
69
|
-
return unless event_attrs
|
|
181
|
+
private
|
|
70
182
|
|
|
71
|
-
|
|
183
|
+
# @return [PgEventstore::StreamsGlobalIndexQueries]
|
|
184
|
+
def streams_global_index_queries
|
|
185
|
+
StreamsGlobalIndexQueries.new(connection, QueryStrategy::Foreground.new(connection))
|
|
72
186
|
end
|
|
73
187
|
|
|
74
|
-
|
|
188
|
+
# @return [PgEventstore::TransactionQueries]
|
|
189
|
+
def transaction_queries
|
|
190
|
+
TransactionQueries.new(connection)
|
|
191
|
+
end
|
|
75
192
|
|
|
76
|
-
# @return [PgEventstore::
|
|
77
|
-
def
|
|
78
|
-
|
|
193
|
+
# @return [PgEventstore::PartitionQueries]
|
|
194
|
+
def partition_queries
|
|
195
|
+
PartitionQueries.new(connection)
|
|
79
196
|
end
|
|
80
197
|
end
|
|
81
198
|
end
|
|
@@ -9,8 +9,9 @@ module PgEventstore
|
|
|
9
9
|
private :connection
|
|
10
10
|
|
|
11
11
|
# @param connection [PgEventstore::Connection]
|
|
12
|
-
def initialize(connection)
|
|
12
|
+
def initialize(connection, query_strategy = QueryStrategy::Foreground.new(connection))
|
|
13
13
|
@connection = connection
|
|
14
|
+
@query_strategy = query_strategy
|
|
14
15
|
end
|
|
15
16
|
|
|
16
17
|
# @param stream [PgEventstore::Stream]
|
|
@@ -28,24 +29,18 @@ module PgEventstore
|
|
|
28
29
|
INSERT INTO partitions (#{attributes.keys.join(', ')})
|
|
29
30
|
VALUES (#{Utils.positional_vars(attributes.values)}) RETURNING *
|
|
30
31
|
SQL
|
|
31
|
-
|
|
32
|
+
connection.with do |conn|
|
|
32
33
|
conn.exec_params(partition_sql, [*attributes.values])
|
|
33
34
|
end.to_a.first
|
|
34
|
-
connection.with do |conn|
|
|
35
|
-
conn.exec(<<~SQL)
|
|
36
|
-
CREATE TABLE #{attributes[:table_name]} PARTITION OF events
|
|
37
|
-
FOR VALUES IN('#{conn.escape_string(stream.context)}') PARTITION BY LIST (stream_name)
|
|
38
|
-
SQL
|
|
39
|
-
end
|
|
40
|
-
partition
|
|
41
35
|
end
|
|
42
36
|
|
|
43
37
|
# @param stream [PgEventstore::Stream]
|
|
44
|
-
# @param
|
|
38
|
+
# @param context_partition_id [Integer]
|
|
45
39
|
# @return [Hash] partition attributes
|
|
46
|
-
def create_stream_name_partition(stream,
|
|
40
|
+
def create_stream_name_partition(stream, context_partition_id)
|
|
47
41
|
attributes = {
|
|
48
|
-
context: stream.context, stream_name: stream.stream_name, table_name: stream_name_partition_name(stream)
|
|
42
|
+
context: stream.context, stream_name: stream.stream_name, table_name: stream_name_partition_name(stream),
|
|
43
|
+
parent_context_partition_id: context_partition_id
|
|
49
44
|
}
|
|
50
45
|
|
|
51
46
|
loop do
|
|
@@ -58,26 +53,22 @@ module PgEventstore
|
|
|
58
53
|
INSERT INTO partitions (#{attributes.keys.join(', ')})
|
|
59
54
|
VALUES (#{Utils.positional_vars(attributes.values)}) RETURNING *
|
|
60
55
|
SQL
|
|
61
|
-
|
|
56
|
+
connection.with do |conn|
|
|
62
57
|
conn.exec_params(partition_sql, [*attributes.values])
|
|
63
58
|
end.to_a.first
|
|
64
|
-
connection.with do |conn|
|
|
65
|
-
conn.exec(<<~SQL)
|
|
66
|
-
CREATE TABLE #{attributes[:table_name]} PARTITION OF #{context_partition_name}
|
|
67
|
-
FOR VALUES IN('#{conn.escape_string(stream.stream_name)}') PARTITION BY LIST (type)
|
|
68
|
-
SQL
|
|
69
|
-
end
|
|
70
|
-
partition
|
|
71
59
|
end
|
|
72
60
|
|
|
73
61
|
# @param stream [PgEventstore::Stream]
|
|
74
62
|
# @param event_type [String]
|
|
75
|
-
# @param
|
|
63
|
+
# @param context_partition_id [Integer]
|
|
64
|
+
# @param stream_name_partition_id [Integer]
|
|
76
65
|
# @return [Hash] partition attributes
|
|
77
|
-
def create_event_type_partition(stream, event_type,
|
|
66
|
+
def create_event_type_partition(stream, event_type, context_partition_id,
|
|
67
|
+
stream_name_partition_id)
|
|
78
68
|
attributes = {
|
|
79
69
|
context: stream.context, stream_name: stream.stream_name, event_type:,
|
|
80
|
-
table_name: event_type_partition_name(stream, event_type)
|
|
70
|
+
table_name: event_type_partition_name(stream, event_type), parent_context_partition_id: context_partition_id,
|
|
71
|
+
parent_stream_name_partition_id: stream_name_partition_id
|
|
81
72
|
}
|
|
82
73
|
|
|
83
74
|
loop do
|
|
@@ -90,16 +81,9 @@ module PgEventstore
|
|
|
90
81
|
INSERT INTO partitions (#{attributes.keys.join(', ')})
|
|
91
82
|
VALUES (#{Utils.positional_vars(attributes.values)}) RETURNING *
|
|
92
83
|
SQL
|
|
93
|
-
|
|
84
|
+
connection.with do |conn|
|
|
94
85
|
conn.exec_params(partition_sql, [*attributes.values])
|
|
95
86
|
end.to_a.first
|
|
96
|
-
connection.with do |conn|
|
|
97
|
-
conn.exec(<<~SQL)
|
|
98
|
-
CREATE TABLE #{attributes[:table_name]} PARTITION OF #{stream_name_partition_name}
|
|
99
|
-
FOR VALUES IN('#{conn.escape_string(event_type)}')
|
|
100
|
-
SQL
|
|
101
|
-
end
|
|
102
|
-
partition
|
|
103
87
|
end
|
|
104
88
|
|
|
105
89
|
# @param stream [PgEventstore::Stream]
|
|
@@ -117,9 +101,15 @@ module PgEventstore
|
|
|
117
101
|
|
|
118
102
|
context_partition = context_partition(stream) || create_context_partition(stream)
|
|
119
103
|
stream_name_partition =
|
|
120
|
-
stream_name_partition(stream) ||
|
|
104
|
+
stream_name_partition(stream) ||
|
|
105
|
+
create_stream_name_partition(stream, context_partition['id'])
|
|
121
106
|
|
|
122
|
-
create_event_type_partition(
|
|
107
|
+
create_event_type_partition(
|
|
108
|
+
stream,
|
|
109
|
+
event_type,
|
|
110
|
+
context_partition['id'],
|
|
111
|
+
stream_name_partition['id']
|
|
112
|
+
)
|
|
123
113
|
end
|
|
124
114
|
|
|
125
115
|
# @param stream [PgEventstore::Stream]
|
|
@@ -171,47 +161,15 @@ module PgEventstore
|
|
|
171
161
|
# @param ids [Array<Integer>]
|
|
172
162
|
# @return [Array<Hash>]
|
|
173
163
|
def find_by_ids(ids)
|
|
174
|
-
|
|
175
|
-
conn.exec_params('select * from partitions where id = ANY($1::bigint[])', [ids])
|
|
176
|
-
end.to_a
|
|
164
|
+
@query_strategy.exec_params('select * from partitions where id = ANY($1::bigint[])', [ids]).to_a
|
|
177
165
|
end
|
|
178
166
|
|
|
179
|
-
# @param
|
|
180
|
-
# @param event_filters [Array<String>]
|
|
167
|
+
# @param filters_collection [PgEventstore::QueryBuilders::Filters::Collection]
|
|
181
168
|
# @param scope [Symbol] what kind of partition we want to receive. Available options are :event_type, :context,
|
|
182
169
|
# :stream_name and :auto. In :auto mode the scope will be calculated based on stream_filters and event_filters.
|
|
183
170
|
# @return [Array<PgEventstore::Partition>]
|
|
184
|
-
def partitions(
|
|
185
|
-
|
|
186
|
-
sql_builder =
|
|
187
|
-
if event_filters.any?
|
|
188
|
-
# When event type filters are present - they apply constraints to any stream filter. Thus, we can't look up
|
|
189
|
-
# partitions by stream attributes separately.
|
|
190
|
-
filter = QueryBuilders::PartitionsFiltering.new
|
|
191
|
-
stream_filters.each { |attrs| filter.add_stream_attrs(**attrs) }
|
|
192
|
-
filter.add_event_types(event_filters)
|
|
193
|
-
set_partitions_scope(filter, stream_filters, event_filters, scope)
|
|
194
|
-
else
|
|
195
|
-
# When event type filters are absent - we can look up partitions by context and context/stream_name
|
|
196
|
-
# separately, thus potentially producing one-to-one mapping of filter-to-partition with :auto scope. For
|
|
197
|
-
# example, let's say we have stream attributes filter like
|
|
198
|
-
# [{ context: 'FooCtx', stream_name: 'Bar'}, { context: 'BarCtx' }], then we would be able to look up
|
|
199
|
-
# partitions by the exact match, returning only two of them according to the provided filters - stream
|
|
200
|
-
# partition for first filter and context partition for second filter.
|
|
201
|
-
builders = stream_filters.map do |attrs|
|
|
202
|
-
filter = QueryBuilders::PartitionsFiltering.new
|
|
203
|
-
filter.add_stream_attrs(**attrs)
|
|
204
|
-
set_partitions_scope(filter, [attrs], event_filters, scope)
|
|
205
|
-
end
|
|
206
|
-
|
|
207
|
-
sql_builder = SQLBuilder.union_builders(builders) if builders.any?
|
|
208
|
-
sql_builder ||
|
|
209
|
-
begin
|
|
210
|
-
builder = QueryBuilders::PartitionsFiltering.new
|
|
211
|
-
set_partitions_scope(builder, stream_filters, event_filters, scope)
|
|
212
|
-
end
|
|
213
|
-
end
|
|
214
|
-
|
|
171
|
+
def partitions(filters_collection, scope: :event_type)
|
|
172
|
+
sql_builder = QueryBuilders::PartitionsFiltering.assemble_sql_builder(filters_collection, scope:)
|
|
215
173
|
connection.with do |conn|
|
|
216
174
|
conn.exec_params(*sql_builder.to_exec_params)
|
|
217
175
|
end.map(&method(:deserialize))
|
|
@@ -236,45 +194,29 @@ module PgEventstore
|
|
|
236
194
|
"event_types_#{Digest::MD5.hexdigest("#{stream.context}-#{stream.stream_name}-#{event_type}")[0..5]}"
|
|
237
195
|
end
|
|
238
196
|
|
|
239
|
-
|
|
197
|
+
# @param partition [PgEventstore::Partition]
|
|
198
|
+
# @return [void]
|
|
199
|
+
def detach_event_type_partition(partition)
|
|
200
|
+
parent = deserialize(find_by_ids([partition.parent_stream_name_partition_id]).first)
|
|
201
|
+
connection.with do |conn|
|
|
202
|
+
conn.exec("alter table #{parent.table_name} detach partition #{partition.table_name}")
|
|
203
|
+
end
|
|
204
|
+
end
|
|
240
205
|
|
|
241
|
-
# @param
|
|
242
|
-
# @
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
partitions_filter.with_event_types
|
|
250
|
-
when :stream_name
|
|
251
|
-
filter = QueryBuilders::PartitionsFiltering.new
|
|
252
|
-
filter.without_event_types
|
|
253
|
-
filter.with_stream_names
|
|
254
|
-
builder = filter.to_sql_builder
|
|
255
|
-
builder.where(
|
|
256
|
-
'(context, stream_name) in ?',
|
|
257
|
-
partitions_filter.to_sql_builder.unselect.select('context, stream_name').group('context, stream_name')
|
|
206
|
+
# @param partition [PgEventstore::Partition]
|
|
207
|
+
# @return [void]
|
|
208
|
+
def attach_event_type_partition(partition)
|
|
209
|
+
parent = deserialize(find_by_ids([partition.parent_stream_name_partition_id]).first)
|
|
210
|
+
connection.with do |conn|
|
|
211
|
+
event_type = conn.escape_string(partition.event_type)
|
|
212
|
+
conn.exec(
|
|
213
|
+
"alter table #{parent.table_name} attach partition #{partition.table_name} for values in ('#{event_type}')"
|
|
258
214
|
)
|
|
259
|
-
when :context
|
|
260
|
-
filter = QueryBuilders::PartitionsFiltering.new
|
|
261
|
-
filter.without_event_types
|
|
262
|
-
filter.without_stream_names
|
|
263
|
-
builder = filter.to_sql_builder
|
|
264
|
-
builder.where('context in ?', partitions_filter.to_sql_builder.unselect.select('context').group('context'))
|
|
265
|
-
when :auto
|
|
266
|
-
if event_filters.any?
|
|
267
|
-
set_partitions_scope(partitions_filter, stream_filters, event_filters, :event_type)
|
|
268
|
-
elsif stream_filters.any? { _1[:stream_name] }
|
|
269
|
-
set_partitions_scope(partitions_filter, stream_filters, event_filters, :stream_name)
|
|
270
|
-
else
|
|
271
|
-
set_partitions_scope(partitions_filter, stream_filters, event_filters, :context)
|
|
272
|
-
end
|
|
273
|
-
else
|
|
274
|
-
raise NotImplementedError, "Don't know how to handle #{scope.inspect} scope!"
|
|
275
215
|
end
|
|
276
216
|
end
|
|
277
217
|
|
|
218
|
+
private
|
|
219
|
+
|
|
278
220
|
# @param attrs [Hash]
|
|
279
221
|
# @return [PgEventstore::Partition]
|
|
280
222
|
def deserialize(attrs)
|