Exemple #1
0
        internal async Task <long> CommitToPersistence(StringBuilder dmlCollector, long?position)
        {
            if (position.HasValue == false)
            {
                throw new ArgumentException("Commit's must have a position", nameof(position));
            }

            using (var readDb = SqlExecution.OpenWriteConnection(_commitConnectionstring))
            {
                //Consider a write-lock around _dmlCollector, is it necessary?
                //Consider pre-pending a "BEGIN TRANSACTION" and have a all-or-nothing write
                dmlCollector.PrependLine("SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED; BEGIN TRANSACTION;");
                dmlCollector.AppendLine(
                    $"UPDATE Inf_ReadSubscriptions SET ReadPosition = {position.Value} WHERE SchemaName = '{_projection.SchemaIdentifier.Name}';");
                dmlCollector.AppendLine("COMMIT TRANSACTION;");

                var dml    = new SqlCommand(dmlCollector.ToString(), readDb);
                var effect = await dml.ExecuteNonQueryAsync();

                if (effect == 0)
                {
                    throw new InvalidOperationException(
                              "Something went wrong while updating the state of a readservice. SQL:\r\n" + dmlCollector);
                }

                //todo: Error handling?

                return(position.Value);
            }
        }
Exemple #2
0
        internal IEnumerable <SqlProjectionSubscription> WakeReadProjections(ISqlProjection[] projections)
        {
            // Subscriptions are scoped as: 1 instance per 'SchemaName' per database (connectionstring becomes the partition-key)
            using (var connection = SqlExecution.OpenWriteConnection(_connectionString))
            {
                var existingSubscriptions = connection.Query(
                    "SELECT SchemaName, SchemaRevision, ReadPosition FROM Inf_ReadSubscriptions")
                                            .Select(x => new
                {
                    SchemaName     = (string)x.SchemaName,
                    SchemaRevision = (string)x.SchemaRevision,
                    ReadPosition   = (long?)x.ReadPosition
                }).ToDictionary(x => x.SchemaName);


                foreach (var projection in projections)
                {
                    if (existingSubscriptions.TryGetValue(projection.SchemaIdentifier.Name, out var state) &&
                        projection.SchemaIdentifier.Revision.Equals(state.SchemaRevision))
                    {
                        yield return(WakeReadProjection(projection, new SubscriptionState
                        {
                            AlreadyExists = true,
                            ReadPosition = state.ReadPosition
                        }, connection));
                    }
                    else
                    {
                        //if not already existing (or existing in another revision), (re)register it
                        yield return(WakeReadProjection(projection, new SubscriptionState
                        {
                            AlreadyExists = false,
                            ReadPosition = null
                        }, connection));
                    }
                }
            }
        }
Exemple #3
0
 private static void PrepareSubscriptionSchema(string sqlConnectionString)
 {
     using (SqlConnection connection = SqlExecution.OpenWriteConnection(sqlConnectionString))
         SqlExecution.Run(_subscriberSchemaSetup, connection);
 }