public EstablishTombstoneStream(EventGraph events)
        {
            var pkFields = events.TenancyStyle == TenancyStyle.Conjoined
                ? "id, tenant_id"
                : "id";

            _sql = $@"
insert into {events.DatabaseSchemaName}.mt_streams (id, tenant_id, version)
values (?, '*DEFAULT*', 0)
ON CONFLICT ({pkFields})
DO NOTHING
";

            if (events.StreamIdentity == StreamIdentity.AsGuid)
            {
                _configureParameter = p =>
                {
                    p.Value        = StreamId;
                    p.NpgsqlDbType = NpgsqlDbType.Uuid;
                };
            }
            else
            {
                _configureParameter = p =>
                {
                    p.Value        = StreamKey;
                    p.NpgsqlDbType = NpgsqlDbType.Varchar;
                };
            }
        }
Пример #2
0
 public void AddEventsAndEdges(IEnumerable <EventEdge <AbstractEvent> > edges)
 {
     foreach (EventEdge <AbstractEvent> edge in edges)
     {
         EventGraph.AddVerticesAndEdge(edge);
     }
 }
Пример #3
0
 public StoreOptions()
 {
     Events     = new EventGraph(this);
     Schema     = new MartenRegistry();
     Transforms = new Transforms.Transforms(this);
     Storage    = new StorageFeatures(this);
 }
Пример #4
0
 public void GenerateAppendCode(GeneratedMethod method, EventGraph graph, int index)
 {
     method.Frames.Code($"parameters[{index}].{nameof(NpgsqlParameter.NpgsqlDbType)} = {{0}};",
                        NpgsqlDbType);
     method.Frames.Code(
         $"parameters[{index}].{nameof(NpgsqlParameter.Value)} = {{0}}.{_member.Name};", Use.Type <IEvent>());
 }
Пример #5
0
 public void GenerateSelectorCodeAsync(GeneratedMethod method, EventGraph graph, int index)
 {
     method.IfDbReaderValueIsNotNull(index, () =>
     {
         method.AssignMemberFromReader(null, index, _eventMemberExpression);
     });
 }
Пример #6
0
        public HighWaterDetector(ITenant tenant, EventGraph graph)
        {
            _tenant = tenant;

            _findSafeSequence = new NpgsqlCommand($@"select min(seq_id) from {graph.DatabaseSchemaName}.mt_events where mt_events.timestamp >= :timestamp");
            _safeTimestamp    = _findSafeSequence.AddNamedParameter("timestamp", DateTimeOffset.MinValue);

            _gapDetection = new NpgsqlCommand($@"
select seq_id
from   (select
               seq_id,
               lead(seq_id)
               over (order by seq_id) as no
        from
               {graph.DatabaseSchemaName}.mt_events where seq_id > :start) ct
where  no is not null
  and    no - seq_id > 1
LIMIT 1;
select max(seq_id) from {graph.DatabaseSchemaName}.mt_events where seq_id > :start;
".Trim());

            _start = _gapDetection.AddNamedParameter("start", 0L);

            _stateDetection = new NpgsqlCommand($@"
select last_value from {graph.DatabaseSchemaName}.mt_events_sequence;
select last_seq_id, last_updated, transaction_timestamp() as timestamp from {graph.DatabaseSchemaName}.mt_event_progression where name = '{ShardState.HighWaterMark}';
".Trim());

            _updateStatus =
                new NpgsqlCommand($"select {graph.DatabaseSchemaName}.mt_mark_event_progression('{ShardState.HighWaterMark}', :seq);");
            _newSeq = _updateStatus.AddNamedParameter("seq", 0L);
        }
Пример #7
0
 public void GenerateSelectorCodeSync(GeneratedMethod method, EventGraph graph, int index)
 {
     method.IfDbReaderValueIsNotNull(index, () =>
     {
         method.AssignMemberFromReader <IEvent>(null, index, x => x.CorrelationId);
     });
 }
        private static GeneratedType buildAppendEventOperation(EventGraph graph, GeneratedAssembly assembly)
        {
            var operationType = assembly.AddType("AppendEventOperation", typeof(AppendEventOperationBase));

            var configure = operationType.MethodFor(nameof(AppendEventOperationBase.ConfigureCommand));

            configure.DerivedVariables.Add(new Variable(typeof(IEvent), nameof(AppendEventOperationBase.Event)));
            configure.DerivedVariables.Add(new Variable(typeof(StreamAction), nameof(AppendEventOperationBase.Stream)));

            var columns = new EventsTable(graph).SelectColumns()

                          // Hokey, use an explicit model for writeable vs readable columns some day
                          .Where(x => !(x is IsArchivedColumn)).ToList();

            var sql =
                $"insert into {graph.DatabaseSchemaName}.mt_events ({columns.Select(x => x.Name).Join(", ")}) values ({columns.Select(_ => "?").Join(", ")})";

            configure.Frames.Code($"var parameters = {{0}}.{nameof(CommandBuilder.AppendWithParameters)}(\"{sql}\");",
                                  Use.Type <CommandBuilder>());

            for (var i = 0; i < columns.Count; i++)
            {
                columns[i].GenerateAppendCode(configure, graph, i);
            }

            return(operationType);
        }
        private static void buildConfigureCommandMethodForStreamState(EventGraph graph, GeneratedType streamQueryHandlerType)
        {
            var sql =
                $"select id, version, type, timestamp, created as timestamp, is_archived from {graph.DatabaseSchemaName}.mt_streams where id = ?";

            if (graph.TenancyStyle == TenancyStyle.Conjoined)
            {
                streamQueryHandlerType.AllInjectedFields.Add(new InjectedField(typeof(string), "tenantId"));
                sql += $" and {TenantIdColumn.Name} = ?";
            }

            var configureCommand = streamQueryHandlerType.MethodFor("ConfigureCommand");

            configureCommand.Frames.Call <CommandBuilder>(x => x.AppendWithParameters(""), @call =>
            {
                @call.Arguments[0] = Constant.ForString(sql);
                @call.ReturnAction = ReturnAction.Initialize;
            });

            var idDbType = graph.StreamIdentity == StreamIdentity.AsGuid ? DbType.Guid : DbType.String;

            configureCommand.Frames.Code("{0}[0].Value = _streamId;", Use.Type <NpgsqlParameter[]>());
            configureCommand.Frames.Code("{0}[0].DbType = {1};", Use.Type <NpgsqlParameter[]>(), idDbType);

            if (graph.TenancyStyle == TenancyStyle.Conjoined)
            {
                configureCommand.Frames.Code("{0}[1].Value = _tenantId;", Use.Type <NpgsqlParameter[]>());
                configureCommand.Frames.Code("{0}[1].DbType = {1};", Use.Type <NpgsqlParameter[]>(), DbType.String);
            }
        }
        private static GeneratedType buildInsertStream(GeneratedType builderType, GeneratedAssembly generatedAssembly,
                                                       EventGraph graph)
        {
            var operationType = generatedAssembly.AddType(InsertStreamOperationName, typeof(InsertStreamBase));

            var columns = new StreamsTable(graph)
                          .Columns
                          .OfType <IStreamTableColumn>()
                          .Where(x => x.Writes)
                          .ToArray();

            var sql = $"insert into {graph.DatabaseSchemaName}.mt_streams ({columns.Select(x => x.Name).Join(", ")}) values ({columns.Select(_ => "?").Join(", ")})";
            var configureCommand = operationType.MethodFor("ConfigureCommand");

            configureCommand.DerivedVariables.Add(new Variable(typeof(StreamAction), nameof(InsertStreamBase.Stream)));

            configureCommand.Frames.Code($"var parameters = {{0}}.{nameof(CommandBuilder.AppendWithParameters)}(\"{sql}\");",
                                         Use.Type <CommandBuilder>());

            for (var i = 0; i < columns.Length; i++)
            {
                columns[i].GenerateAppendCode(configureCommand, i);
            }

            builderType.MethodFor(nameof(EventDocumentStorage.InsertStream))
            .Frames.Code($"return new Marten.Generated.{InsertStreamOperationName}(stream);");

            return(operationType);
        }
        public HighWaterStatisticsDetector(EventGraph graph)
        {
            _stateDetection = new NpgsqlCommand($@"
select last_value from {graph.DatabaseSchemaName}.mt_events_sequence;
select last_seq_id, last_updated, transaction_timestamp() as timestamp from {graph.DatabaseSchemaName}.mt_event_progression where name = '{ShardState.HighWaterMark}';
".Trim());
        }
Пример #12
0
 public StreamIdColumn(EventGraph graph) : base("stream_id", "varchar")
 {
     Type      = graph.GetStreamIdDBType();
     Directive = graph.TenancyStyle != TenancyStyle.Conjoined
         ? $"REFERENCES {graph.DatabaseSchemaName}.mt_streams ON DELETE CASCADE"
         : null;
 }
Пример #13
0
 public void GenerateSelectorCodeAsync(GeneratedMethod method, EventGraph graph, int index)
 {
     method.IfDbReaderValueIsNotNullAsync(index, () =>
     {
         method.AssignMemberFromReaderAsync <IEvent>(null, index, x => x.TenantId);
     });
 }
Пример #14
0
        private static GeneratedType buildStreamQueryHandlerType(EventGraph graph, GeneratedAssembly assembly)
        {
            var streamQueryHandlerType =
                assembly.AddType(StreamStateSelectorTypeName, typeof(StreamStateQueryHandler));

            streamQueryHandlerType.AllInjectedFields.Add(graph.StreamIdentity == StreamIdentity.AsGuid
                ? new InjectedField(typeof(Guid), "streamId")
                : new InjectedField(typeof(string), "streamId"));

            buildConfigureCommandMethodForStreamState(graph, streamQueryHandlerType);

            var sync  = streamQueryHandlerType.MethodFor("Resolve");
            var async = streamQueryHandlerType.MethodFor("ResolveAsync");


            sync.Frames.Add(new ConstructorFrame <StreamState>(() => new StreamState()));
            async.Frames.Add(new ConstructorFrame <StreamState>(() => new StreamState()));

            if (graph.StreamIdentity == StreamIdentity.AsGuid)
            {
                sync.AssignMemberFromReader <StreamState>(streamQueryHandlerType, 0, x => x.Id);
                async.AssignMemberFromReaderAsync <StreamState>(streamQueryHandlerType, 0, x => x.Id);
            }
            else
            {
                sync.AssignMemberFromReader <StreamState>(streamQueryHandlerType, 0, x => x.Key);
                async.AssignMemberFromReaderAsync <StreamState>(streamQueryHandlerType, 0, x => x.Key);
            }

            sync.AssignMemberFromReader <StreamState>(streamQueryHandlerType, 1, x => x.Version);
            async.AssignMemberFromReaderAsync <StreamState>(streamQueryHandlerType, 1, x => x.Version);

            sync.Frames.Call <StreamStateQueryHandler>(x => x.SetAggregateType(null, null, null), call =>
            {
                call.IsLocal = true;
            });

#pragma warning disable 4014
            async.Frames.Call <StreamStateQueryHandler>(
                x => x.SetAggregateTypeAsync(null, null, null, CancellationToken.None), call =>
#pragma warning restore 4014
            {
                call.IsLocal = true;
            });

            sync.AssignMemberFromReader <StreamState>(streamQueryHandlerType, 3, x => x.LastTimestamp);
            async.AssignMemberFromReaderAsync <StreamState>(streamQueryHandlerType, 3, x => x.LastTimestamp);

            sync.AssignMemberFromReader <StreamState>(streamQueryHandlerType, 4, x => x.Created);
            async.AssignMemberFromReaderAsync <StreamState>(streamQueryHandlerType, 4, x => x.Created);

            sync.AssignMemberFromReader <StreamState>(streamQueryHandlerType, 5, x => x.IsArchived);
            async.AssignMemberFromReaderAsync <StreamState>(streamQueryHandlerType, 5, x => x.IsArchived);

            sync.Frames.Return(typeof(StreamState));
            async.Frames.Return(typeof(StreamState));

            return(streamQueryHandlerType);
        }
Пример #15
0
        public EventAppender(EventGraph graph, EventDocumentStorage builder, IInlineProjection[] projections)
        {
            _graph       = graph;
            _builder     = builder;
            _projections = projections;

            // TODO -- track the event streams separately within the DocumentSessionBase
        }
Пример #16
0
        public StreamActionTester()
        {
            theSession = Substitute.For <IMartenSession>();
            theSession.TenantId.Returns("TX");
            theSession.Database.Returns(Substitute.For <IMartenDatabase>());

            theEvents = new EventGraph(new StoreOptions());
        }
Пример #17
0
        public EventsTable(EventGraph events) : base(new DbObjectName(events.DatabaseSchemaName, "mt_events"))
        {
            AddColumn(new EventTableColumn("seq_id", x => x.Sequence)).AsPrimaryKey();
            AddColumn(new EventTableColumn("id", x => x.Id)).NotNull();
            AddColumn(new StreamIdColumn(events));

            AddColumn(new EventTableColumn("version", x => x.Version)).NotNull();
            AddColumn <EventJsonDataColumn>();
            AddColumn <EventTypeColumn>();
            AddColumn(new EventTableColumn("timestamp", x => x.Timestamp))
            .NotNull().DefaultValueByString("(now())");

            AddColumn <TenantIdColumn>();

            AddColumn <DotNetTypeColumn>().AllowNulls();

            AddIfActive(events.Metadata.CorrelationId);
            AddIfActive(events.Metadata.CausationId);
            AddIfActive(events.Metadata.Headers);

            if (events.TenancyStyle == TenancyStyle.Conjoined)
            {
                ForeignKeys.Add(new ForeignKey("fkey_mt_events_stream_id_tenant_id")
                {
                    ColumnNames = new string[] { "stream_id", TenantIdColumn.Name },
                    LinkedNames = new string[] { "id", TenantIdColumn.Name },
                    LinkedTable = new DbObjectName(events.DatabaseSchemaName, "mt_streams")
                });

                Indexes.Add(new IndexDefinition("pk_mt_events_stream_and_version")
                {
                    IsUnique = true,
                    Columns  = new string[] { "stream_id", TenantIdColumn.Name, "version" }
                });
            }
            else
            {
                ForeignKeys.Add(new ForeignKey("fkey_mt_events_stream_id")
                {
                    ColumnNames = new string[] { "stream_id" },
                    LinkedNames = new string[] { "id" },
                    LinkedTable = new DbObjectName(events.DatabaseSchemaName, "mt_streams"),
                    OnDelete    = CascadeAction.Cascade
                });

                Indexes.Add(new IndexDefinition("pk_mt_events_stream_and_version")
                {
                    IsUnique = true,
                    Columns  = new string[] { "stream_id", "version" }
                });
            }

            Indexes.Add(new IndexDefinition("pk_mt_events_id_unique")
            {
                Columns  = new string[] { "id" },
                IsUnique = true
            });
        }
Пример #18
0
        internal IStorageOperation BuildProgressionOperation(EventGraph events)
        {
            if (SequenceFloor == 0)
            {
                return(new InsertProjectionProgress(events, this));
            }

            return(new UpdateProjectionProgress(events, this));
        }
Пример #19
0
        public StreamActionTester()
        {
            theSession = Substitute.For <IMartenSession>();
            theTenant  = Substitute.For <ITenant>();
            theSession.Tenant.Returns(theTenant);
            theTenant.TenantId.Returns("TX");

            theEvents = new EventGraph(new StoreOptions());
        }
Пример #20
0
        public DocumentSchema(StoreOptions options, IConnectionFactory factory, IDocumentSchemaCreation creation)
        {
            _factory  = factory;
            _creation = creation;

            StoreOptions = options;

            Sequences = new SequenceFactory(this, _factory, _creation);

            Events = new EventGraph();
        }
Пример #21
0
        public DocumentSchema(StoreOptions options, ICommandRunner runner, IDocumentSchemaCreation creation)
        {
            _creation = creation;
            _runner   = runner;

            StoreOptions = options;

            Sequences = new SequenceFactory(this, _runner, _creation);

            Events = new EventGraph();
        }
Пример #22
0
        public HighWaterDetector(ISingleQueryRunner runner, EventGraph graph)
        {
            _runner                      = runner;
            _gapDetector                 = new GapDetector(graph);
            _safeSequenceFinder          = new SafeSequenceFinder(graph);
            _highWaterStatisticsDetector = new HighWaterStatisticsDetector(graph);

            _updateStatus =
                new NpgsqlCommand($"select {graph.DatabaseSchemaName}.mt_mark_event_progression('{ShardState.HighWaterMark}', :seq);");
            _newSeq = _updateStatus.AddNamedParameter("seq", 0L);
        }
Пример #23
0
 public void GenerateSelectorCodeAsync(GeneratedMethod method, EventGraph graph, int index)
 {
     if (graph.StreamIdentity == StreamIdentity.AsGuid)
     {
         method.AssignMemberFromReaderAsync <IEvent>(null, index, x => x.StreamId);
     }
     else
     {
         method.AssignMemberFromReaderAsync <IEvent>(null, index, x => x.StreamKey);
     }
 }
Пример #24
0
 public void GenerateAppendCode(GeneratedMethod method, EventGraph graph, int index)
 {
     if (graph.StreamIdentity == StreamIdentity.AsGuid)
     {
         method.SetParameterFromMember <StreamAction>(index, x => x.Id);
     }
     else
     {
         method.SetParameterFromMember <StreamAction>(index, x => x.Key);
     }
 }
Пример #25
0
        public ProjectionTrack(IFetcher fetcher, IDocumentStore store, IProjection projection, IDaemonLogger logger, IDaemonErrorHandler errorHandler)
        {
            _fetcher      = fetcher;
            _projection   = projection;
            _logger       = logger;
            _errorHandler = errorHandler;
            _store        = store;

            _events = store.Schema.Events;

            ViewType = _projection.Produces;
        }
Пример #26
0
        public ProjectionTrack(IFetcher fetcher, IDocumentStore store, IProjection projection, IDaemonLogger logger, IDaemonErrorHandler errorHandler)
        {
            _fetcher = fetcher;
            _projection = projection;
            _logger = logger;
            _errorHandler = errorHandler;
            _store = store;

            _events = store.Schema.Events;

            ViewType = _projection.Produces;
        }
Пример #27
0
        public void use_string_id_if_as_string_identifiers()
        {
            var events = new EventGraph(new StoreOptions())
            {
                StreamIdentity = StreamIdentity.AsString
            };

            var table = new StreamsTable(events);

            table.PrimaryKey.Type.ShouldBe("varchar");
            table.First().Name.ShouldBe("id");
        }
Пример #28
0
        public StoreOptions()
        {
            Events     = new EventGraph(this);
            Schema     = new MartenRegistry(this);
            Transforms = new Transforms.Transforms(this);

            var patching = new TransformFunction(this, PatchDoc, SchemaBuilder.GetJavascript(this, "mt_patching"));

            patching.OtherArgs.Add("patch");

            Transforms.Load(patching);
        }
Пример #29
0
        public void use_the_plain_append_event_function_when_async_and_js_are_disabled()
        {
            var graph = new EventGraph(new StoreOptions())
            {
                AsyncProjectionsEnabled      = false,
                JavascriptProjectionsEnabled = false
            };

            var storage = new EventStreamStorage(graph);

            storage.AppendEventFunction.Name.ShouldBe("mt_append_event");
        }
Пример #30
0
        public ProjectionTrack(IFetcher fetcher, DocumentStore store, IProjection projection, IDaemonLogger logger, IDaemonErrorHandler errorHandler, ITenant tenant)
        {
            _fetcher      = fetcher;
            _projection   = projection;
            _logger       = logger;
            _errorHandler = errorHandler;
            _tenant       = tenant;
            _store        = store;

            _events = store.Events;

            ViewType = _projection.ProjectedType();
        }
Пример #31
0
        public void use_rolling_buffer_version_of_append_event_function_when_async_is_enabled()
        {
            var graph = new EventGraph(new StoreOptions())
            {
                AsyncProjectionsEnabled      = true,
                JavascriptProjectionsEnabled = false
            };

            var storage = new EventStreamStorage(graph);


            storage.AppendEventFunction.Name.ShouldBe("mt_append_event_with_buffering");
        }
Пример #32
0
 public EventProgressWrite(EventGraph events, string key, long number)
 {
     _sproc = new FunctionName(events.DatabaseSchemaName, "mt_mark_event_progression");
     _key = key;
     _number = number;
 }