public async Task <CommitsLoad> LoadCommitsAsync(string streamId)
        {
            Expect.NotDisposed(isDisposed);
            Expect.NotEmpty(streamId, "streamId");

            var routingInfo = routing.CreateRoutingInfo(streamId);

            return(await Execute(async() =>
            {
                var result = new List <Commit>();

                var conn = await GetOrCreateOpenedConnection(routingInfo).ConfigureAwait(false);
                using (var cmd = SqlCommands.Load(streamId, routingInfo.Partition, schema))
                {
                    cmd.Connection = conn;
                    using (var reader = await cmd.ExecuteReaderAsync().ConfigureAwait(false))
                    {
                        while (reader.Read())
                        {
                            var commit = ReadRowAsCommit(reader);
                            result.Add(commit);
                        }
                    }
                }

                var commits = result.OrderBy(c => c.Version).ToArray();

                return commits.Length > 0
                    ? new CommitsLoad(commits, commits.Last().Version)
                    : CommitsLoad.Empty;
            }).ConfigureAwait(false));
        }
예제 #2
0
        internal static string EnsureStorageForTests(string connectionString, PartitionMap partitionMap)
        {
            var schema = "test" + Guid.NewGuid().ToString("N").Substring(0, 8);
            var source = partitionMap.Hosts.Select(x =>
            {
                var cb = new NpgsqlConnectionStringBuilder(connectionString)
                {
                    Host   = x.Host,
                    Port   = x.Port,
                    Enlist = false,
                };
                return(Builder: cb, x.Partitions);
            });

            Parallel.ForEach(source, src =>
            {
                using (var conn = new NpgsqlConnection(src.Builder.ToString()))
                {
                    conn.Open();
                    using (var cmd = SqlCommands.EnsureSchema(schema, src.Builder.Username))
                    {
                        cmd.Connection = conn;
                        cmd.ExecuteNonQuery();
                    }

                    using (var cmd = SqlCommands.EnsureStorage(src.Partitions, schema))
                    {
                        cmd.Connection = conn;
                        cmd.ExecuteNonQuery();
                    }
                }
            });

            return(schema);
        }
        public async Task <bool> SaveAsync(Commit commit)
        {
            Expect.NotDisposed(isDisposed);
            Expect.NotNull(commit, "commit");
            commit.ThrowIfContainsInvalidData();

            var routingInfo = routing.CreateRoutingInfo(commit.StreamId);

            return(await Execute(async() =>
            {
                var conn = await GetOrCreateOpenedConnection(routingInfo).ConfigureAwait(false);
                using (var cmd = SqlCommands.Save(commit, routingInfo.Partition, schema))
                {
                    cmd.Connection = conn;
                    try
                    {
                        var affected = await cmd.ExecuteNonQueryAsync().ConfigureAwait(false);
                        return affected == 1;
                    }
                    catch (PostgresException ex)
                    {
                        if (ex.SqlState == PgsqlCodeOnDuplicateRec)
                        {
                            throw ToVersionConflict(ex);
                        }

                        throw;
                    }
                }
            }).ConfigureAwait(false));
        }
예제 #4
0
        /// <summary>
        /// Creates partition (table) in the host if it does not exists.
        /// It also creates database schema if it is missing (before it creates the table).
        /// </summary>
        /// <param name="connection">database connection string</param>
        /// <param name="schema">database schema name</param>
        /// <param name="partition">partition number</param>
        public async ValueTask <bool> EnsureStorageIsReadyAsync(NpgsqlConnection connection, string schema, int partition = 0)
        {
            var key = $"{connection.Host}:{connection.Port}/{schema}/{partition}";

            if (FinishedInits.Contains(key))
            {
                return(false);
            }

            try
            {
                await InitLock.WaitAsync().ConfigureAwait(false);

                if (FinishedInits.Contains(key))
                {
                    return(false);
                }

                try
                {
                    // Initialization of internal database tables needs to be created in new dedicated connection
                    // which doesn't enlist to any ambient transactions.
                    var connBuilder = new NpgsqlConnectionStringBuilder(connection.ConnectionString)
                    {
                        Enlist = false,
                    };

                    var owner = connection.GetUserId();
                    using (var conn = new NpgsqlConnection(connBuilder.ToString()))
                        using (var cmd = SqlCommands.EnsureStorage(partition, owner, schema))
                        {
                            await conn.OpenAsync().ConfigureAwait(false);

                            cmd.Connection = conn;
                            await cmd.ExecuteNonQueryAsync().ConfigureAwait(false);
                        }
                }
                catch (PostgresException ex)
                {
                    if (ex.SqlState != "42P07") // 42P07 = duplicate table
                    {
                        throw;
                    }
                }

                FinishedInits.Add(key);
                return(true);
            }
            finally
            {
                InitLock.Release();
            }
        }
예제 #5
0
        internal static void DeleteStorageAfterTests(string connectionString, string schema)
        {
            var connBuilder = new NpgsqlConnectionStringBuilder(connectionString)
            {
                Enlist = false,
            };

            using (var conn = new NpgsqlConnection(connBuilder.ToString()))
                using (var cmd = SqlCommands.DropSchemaIfExists(schema))
                {
                    conn.Open();
                    cmd.Connection = conn;
                    cmd.ExecuteNonQuery();
                }
        }
        public async Task <bool> DeleteAsync(string streamId)
        {
            Expect.NotDisposed(isDisposed);
            Expect.NotEmpty(streamId, "streamId");

            var routingInfo = routing.CreateRoutingInfo(streamId);

            return(await Execute(async() =>
            {
                var conn = await GetOrCreateOpenedConnection(routingInfo).ConfigureAwait(false);
                using (var cmd = SqlCommands.Delete(streamId, routingInfo.Partition, schema))
                {
                    cmd.Connection = conn;
                    var affected = await cmd.ExecuteNonQueryAsync().ConfigureAwait(false);
                    return affected == 1;
                }
            }).ConfigureAwait(false));
        }
예제 #7
0
        internal static string EnsureStorageForTests(string connectionString, string schema = null)
        {
            schema ??= "test" + Guid.NewGuid().ToString("N").Substring(0, 8);
            var cb = new NpgsqlConnectionStringBuilder(connectionString)
            {
                Enlist = false,
            };

            try
            {
                using (var conn = new NpgsqlConnection(cb.ToString()))
                {
                    conn.Open();
                    using (var cmd = SqlCommands.EnsureSchema(schema, cb.Username))
                    {
                        cmd.Connection = conn;
                        cmd.ExecuteNonQuery();
                    }

                    using (var cmd = SqlCommands.EnsureStorage(schema))
                    {
                        cmd.Connection = conn;
                        cmd.ExecuteNonQuery();
                    }
                }
            }
            catch (PostgresException ex)
            {
                if (!IsThrownBecauseItAlreadyExists(ex))
                {
                    throw;
                }
            }

            return(schema);
        }