diff --git a/Itmo.Dev.Platform.sln b/Itmo.Dev.Platform.sln
index f3aa631..9ced147 100644
--- a/Itmo.Dev.Platform.sln
+++ b/Itmo.Dev.Platform.sln
@@ -114,6 +114,11 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Itmo.Dev.Platform.Testing.B
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Itmo.Dev.Platform.Testing.Behavioural.MessagePersistence", "src\Itmo.Dev.Platform.Testing.Behavioural.MessagePersistence\Itmo.Dev.Platform.Testing.Behavioural.MessagePersistence.csproj", "{769371D9-527B-4C23-B45A-04CFC0C653B6}"
EndProject
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "docs", "docs", "{18C776DA-A728-44D2-96B1-C79CD8312D9D}"
+ ProjectSection(SolutionItems) = preProject
+ docs\persistence.md = docs\persistence.md
+ EndProjectSection
+EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
diff --git a/README.md b/README.md
index e0be97d..fbe2875 100644
--- a/README.md
+++ b/README.md
@@ -3,39 +3,6 @@
- [Itmo.Dev.Platform.Common](src/Itmo.Dev.Platform.Common/README.md)
- [Itmo.Dev.Platform.YandexCloud](src/Itmo.Dev.Platform.YandexCloud/README.md)
- [Itmo.Dev.Platform.Kafka](src/Itmo.Dev.Platform.Kafka/README.md)
-- [Itmo.Dev.Platform.Postgres](src/Itmo.Dev.Platform.Postgres/README.md)
+- [Itmo.Dev.Platform.Persistence](docs/persistence.md)
- [Itmo.Dev.Platform.Logging](src/Itmo.Dev.Platform.Logging/README.md)
- [Itmo.Dev.Platform.BackgroundTasks](src/Itmo.Dev.Platform.BackgroundTasks/README.md)
-
-## Package source installation
-
-1. Add `nuget.config` file next to your `*.sln` file (if one does not exists)
-2. Prepare your GitHub personal access token with `packages:read` permission
-3. Add reference to `itmo-is-dev` GitHub nuget repository
- ```xml
-
-
-
-
-
-
-
-
-
-
-
- ```
-4. When prompted for authorization, use your github username as username, and generated PAT as password
-
-Alternatively, you can use CLI to add package source. Code below will add source into your global config.
-If you want to add it into local config, you should run it with option `--configfile nuget.config`
-
-```shell
-dotnet nuget add source --username YOUR_USERNAME --password YOUR_GITHUB_PAT --store-password-in-clear-text --name github "https://nuget.pkg.github.com/itmo-is-dev/index.json"
-```
-
-###
WARNING!
-
-Adding source into local config, will result in credentials be written into local file \
-Be aware that it may lead to credentials leaking into VSC \
-You can store credentials separately from source definition, in global nuget.config
\ No newline at end of file
diff --git a/docs/persistence.md b/docs/persistence.md
new file mode 100644
index 0000000..2452c60
--- /dev/null
+++ b/docs/persistence.md
@@ -0,0 +1,215 @@
+## Itmo.Dev.Platform.Persistence
+
+Библиотека для работы с базами данных. Включает в себя абстракции для подключения к БД, выполнения запросов, управления транзакциями и миграциями.
+
+## Подключение
+
+Библиотека состоит из двух Nuget пакетов: `Itmo.Dev.Platform.Persistence.Abstractions` с абстракциями и
+`Itmo.Dev.Platform.Persistence.Postgres` с реализациями для БД Postgres.
+
+Для регистрации в DI-контейнере необходимо вызвать метод `AddPlatformPersistence`, предварительно зарегистрировав саму
+платформу (метод `AddPlatform`).
+Метод принимает делегат, в котором происходит конфигурация Persistence слоя.
+
+```csharp
+collection.AddPlatformPersistence(persistence => persistence.UsePostgres(postgres => postgres
+ .WithConnectionOptions(static builder => builder
+ .BindConfiguration("Infrastructure:Persistence:Postgres"))
+ .WithMigrationsFrom(typeof(IAssemblyMarker).Assembly)
+ .WithDataSourcePlugin()));
+```
+
+У конфигуратора есть метод расширения `UsePostgres`, который настраивает подключение к PostgreSql. В метод так же передаётся
+делегат, в котором можно параметризовать работу с базой с помощью методов:
+
+- `WithConnectionOptions` - настройка конфигурации подключения к БД.
+- `WithMigrationsFrom` - указание сборки(-ок) с миграциями. Также можно использовать `WithMigrationsFromItems` для указания конкретных типов
+ с миграциями.
+- `WithDataSourcePlugin` - подключение плагинов для `NpgsqlDataSource`. Используемые плагины
+ должны реализовывать `IPostgresDataSourcePlugin`, и фактически позволяют дополнительно настроить `NpgsqlDataSourceBuilder`
+ перед созданием data source.
+
+## Конфигурация
+
+Параметры подключения к БД задаются через `PostgresConnectionOptions`.
+
+### Схема конфигурации
+
+```json
+{
+ "Host": string,
+ "Port": int,
+ "Database": string,
+ "Username": string,
+ "Password": string,
+ "SslMode": string,
+ "Pooling": bool,
+ "MaximumPoolSize": int,
+ "EnableConnectionProviderLogging": bool
+}
+```
+
+- **Host**
+ Адрес хоста PostgreSql. Обязательный параметр, не может быть пустым.
+- **Port**
+ Порт PostgreSql. Обязательный параметр, не может быть пустым или равным 0. Допустимые значения: `1`-`65535`.
+- **Database**
+ Название базы данных. Обязательный параметр, не может быть пустым.
+- **Username**
+ Имя пользователя. Обязательный параметр, не может быть пустым.
+- **Password**
+ Пароль. Обязательный параметр, не может быть пустым.
+- **SslMode**
+ Режим SSL-соединения. Необязательный параметр, по умолчанию пустая строка.
+ Допустимые значения аналогичны Npgsql ([документация](https://www.npgsql.org/doc/api/Npgsql.SslMode.html)): `Disable`, `Allow`, `Prefer`, `Require`, `VerifyCA`, `VerifyFull`.
+- **Pooling**
+ Использование пула соединений (connection pooling). Необязательный параметр, по умолчанию `true`.
+- **MaximumPoolSize**
+ Максимальный размер пула соединений. Необязательный параметр, по умолчанию `10`, должен быть >= `1`.
+- **EnableConnectionProviderLogging**
+ Включение логирования. Необязательный параметр, по умолчанию `false`.
+ Для корректной работы необходимо также добавить платфморменный observability - в DI контейнере
+ вызвать метод `.AddPlatformObservability`
+
+> Валидация значений происходит при старте сервиса. При невалидных значениях сервис не запустится.
+
+### Configuration example
+
+```json
+{
+ "Infrastructure": {
+ "Persistence": {
+ "Postgres": {
+ "Host": "localhost",
+ "Database": "test-db",
+ "Port": 6432,
+ "Username": "postgres",
+ "Password": "postgres",
+ "SslMode": "Prefer",
+ "Pooling": true,
+ "MaximumPoolSize": 10,
+ "EnableConnectionProviderLogging": false
+ }
+ }
+ }
+}
+```
+
+## Подключение к БД и выполнение запросов
+
+### Получение соединения
+
+Для получения соединений с БД используется `IPersistenceConnectionProvider`. с БД используется `IPersistenceConnectionProvider`.
+Провайдер зарегистрирован в DI как Scoped, поэтому сервисы использующие его должны быть зарегистрированы как Scoped или Transient.
+
+Чтобы получить объект соединения, необходимо вызвать метод провайдера `GetConnectionAsync`, который возвращает
+`IPersistenceConnection`.
+
+```csharp
+await using IPersistenceConnection connection = await _connectionProvider.GetConnectionAsync(cancellationToken);
+```
+
+### Создание и настройка команды
+
+Команда создается через метод `CreateCommand` на объекте соединения. Параметры добавляются в fluent стиле:
+
+```csharp
+await using IPersistenceCommand command = connection.CreateCommand(sql)
+ .AddParameter("parameter_1", value1)
+ .AddParameter("parameter_2", value2);
+```
+
+Помимо вышеуказанного `AddParameter(string parameterName, T value)`, у `IPersistenceConnection` существуют другие методы и перегрузки для добавления параметров:
+
+- `AddParameter(DbParameter parameter)` - добавляет сырой `DbParameter`, фактически параметр должен быть типа `NpgsqlParameter`.
+- `AddParameter(string parameterName, T value)` - добавляет именованный параметр произвольного типа.
+- `AddParameter(string parameterName, IEnumerable values)` - добавляет именованный параметр-список.
+ Несмотря на ограничение Npgsql в передаваемом типе коллекции для параметра (`List` или `T[]`), в данный метод можно передавать
+ любой тип, реализующий `IEnumerable`. В sql коде удобно подставлять в `= any(...)` или `in (...)`.
+- `AddJsonParameter(string parameterName, T value, JsonSerializerSettings? serializerSettings = null)` - сериализует переданное значение в json и добавляет как параметр с типом `jsonb`.
+- `AddNullableJsonParameter(string parameterName, T? value, JsonSerializerSettings? serializerSettings = null)` - аналогично `AddJsonParameter`, но поддерживает `null` значения.
+- `AddJsonArrayParameter(string parameterName, IEnumerable values, JsonSerializerSettings? serializerSettings = null)` - сериализует каждый элемент коллекции в json и добавляет как параметр с типом `jsonb[]`.
+- `AddJsonArrayParameter(string parameterName, IEnumerable values)` - добавляет коллекцию строк (уже сериализованных объектов) как параметр с типом `jsonb[]`.
+- `AddMultiArrayStringParameter(string parameterName, IEnumerable> values)` - позволяет добавлять многомерные массивы в качестве параметров.
+ Каждый элемент коллекции 1-го уровня преобразуется в postgres-массив, затем итоговый список добавляется как параметр с типом `text[]`.
+ Для корректной работы в sql, необходимо явно привести каждый элемент списка к ожидаемому postgres-типу (например, `integer[]` или `bigint[]`).
+- `AddMultiArrayStringParameter(string parameterName, IEnumerable> values)` - аналогично `AddMultiArrayStringParameter`, но для строковых значений коллекции.
+
+> При попытке добавить параметр с уже существующим названием будет выброшен `PlatformPersistencePostgresException`.
+
+### Выполнение запросов
+
+Чтение данных реализовано через метод команды `ExecuteReaderAsync`, аналогично `NpgsqlCommand`:
+
+```csharp
+await using DbDataReader reader = await command.ExecuteReaderAsync(cancellationToken);
+
+while (await reader.ReadAsync(cancellationToken))
+{
+ yield return new Model(
+ Id: reader.GetInt64("field_1"),
+ Name: reader.GetString("field_2"));
+}
+```
+
+Выполнение не читающих запросов (DML) реализовано через метод `ExecuteNonQueryAsync`, так же аналогично `NpgsqlCommand`:
+
+```csharp
+await command.ExecuteNonQueryAsync(cancellationToken);
+```
+
+## Транзакции
+
+Для управления транзакциями используется `IPersistenceTransactionProvider`, зарегистрированный в DI как Scoped.
+Соответственно сервисы, использующие его, должны быть зарегистрированы как Scoped или Transient.
+
+Для открытия транзакции используется метод `BeginTransactionAsync` с указанием уровня изоляции.
+Метод возвращает `IPersistenceTransaction` - объект транзакции, который после выполнения операций необходимо закоммитить
+(вызвать метод `CommitAsync`). Все операции, выполненные до вызова этого метода, автоматически попадают в транзакцию.
+
+Если `CommitAsync` не был вызван, транзакция откатывается при `DisposeAsync`.
+
+```csharp
+await using IPersistenceTransaction transaction = await _transactionProvider
+ .BeginTransactionAsync(IsolationLevel.ReadCommitted, cancellationToken);
+
+// выполнение операций через репозитории
+
+await transaction.CommitAsync(cancellationToken);
+```
+
+Фактически реализация `IPersistenceTransaction` использует под капотом `TransactionScope` с указанием параметра scopeOption: `TransactionScopeOption.Required`,
+тем самым представляя собой ту же ambient транзакцию.
+
+## Миграции
+
+Механизм миграций реализован на базе библиотеки FluentMigrator.
+Для написания миграции необходимо наследовать абстрактный класс `SqlMigration`, в котором определены методы `GetUpSql` и `GetUpSql`.
+
+`GetUpSql` - sql-скрипт самой миграции, `GetDownSql` - скрипт отката
+
+```csharp
+[Migration(1, "Initial")]
+public class Initial : SqlMigration
+{
+ protected override string GetUpSql(IServiceProvider serviceProvider)
+ {
+ return """
+ create table example
+ (
+ id bigserial not null primary key,
+ name text not null
+ );
+ """;
+ }
+
+ protected override string GetDownSql(IServiceProvider serviceProvider)
+ {
+ return """
+ drop table example;
+ """;
+ }
+}
+```
+
+Миграции запускаются автоматически при старте приложения. Сборка с миграциями указывается при регистрации в DI, методе `WithMigrationsFrom`.
diff --git a/src/Itmo.Dev.Platform.Persistence.Abstractions/README.md b/src/Itmo.Dev.Platform.Persistence.Abstractions/README.md
index ba94965..679ec46 100644
--- a/src/Itmo.Dev.Platform.Persistence.Abstractions/README.md
+++ b/src/Itmo.Dev.Platform.Persistence.Abstractions/README.md
@@ -1 +1,3 @@
-# Itmo.Dev.Platform.Persistence.Abstractions
\ No newline at end of file
+# Itmo.Dev.Platform.Persistence.Abstractions
+
+Документация: [README.md](https://github.com/itmo-is-dev/platform/blob/master/docs/persistence.md)
\ No newline at end of file
diff --git a/src/Itmo.Dev.Platform.Persistence.Postgres/README.md b/src/Itmo.Dev.Platform.Persistence.Postgres/README.md
index 51dbf7e..5353a37 100644
--- a/src/Itmo.Dev.Platform.Persistence.Postgres/README.md
+++ b/src/Itmo.Dev.Platform.Persistence.Postgres/README.md
@@ -1 +1,3 @@
-# Itmo.Dev.Platform.Persistence.Postgres
\ No newline at end of file
+# Itmo.Dev.Platform.Persistence.Postgres
+
+Документация: [README.md](https://github.com/itmo-is-dev/platform/blob/master/docs/persistence.md)
\ No newline at end of file