|
@@ -76,7 +76,7 @@ ok
|
|
|
<<"database \"some\" does not exist">>,[]}}
|
|
|
```
|
|
|
|
|
|
-Здесь тоже настройки должны быть **map()** или **#epgsql_connection_params{}**.
|
|
|
+Здесь также настройки должны быть **map()** или **#epgsql_connection_params{}**.
|
|
|
|
|
|
Если настройки оказались неправильными, то, вероятно, вы захотите
|
|
|
сообщить об ошибке и остановить ноду.
|
|
@@ -147,20 +147,128 @@ proplist, а не атомарное значение).
|
|
|
|
|
|
## Транзациии
|
|
|
|
|
|
-TODO
|
|
|
+Чтобы выполнить несколько запросов в транзакции, нужно вызывать функцию **epgsql_pool:transaction/2**
|
|
|
+с аргументами:
|
|
|
+- имя пула _atom() | string() | binary()_
|
|
|
+- ваша функция
|
|
|
+
|
|
|
+В функцию передается процесс из пула, и запросы к базе данных нужно выполнять,
|
|
|
+используя этот процесс вместо имени пула.
|
|
|
+
|
|
|
+```
|
|
|
+epgsql_pool:transaction(my_pool,
|
|
|
+ fun(Worker) ->
|
|
|
+ Res1 = epgsql_pool:query(Worker, Query1),
|
|
|
+ ...
|
|
|
+ ResN = epgsql_pool:query(Worker, QueryN)
|
|
|
+ end).
|
|
|
+```
|
|
|
+
|
|
|
+Любое исключение, возникающее внутри функции, отменяет транзакцию.
|
|
|
+
|
|
|
+```
|
|
|
+epgsql_pool:transaction(my_pool,
|
|
|
+ fun(Worker) ->
|
|
|
+ Res1 = epgsql_pool:query(Worker, Query1),
|
|
|
+ ...
|
|
|
+ case SomeData of
|
|
|
+ GoodResult -> do_something;
|
|
|
+ BadResult -> throw(cancel_transaction)
|
|
|
+ end,
|
|
|
+ ResN = epgsql_pool:query(Worker, QueryN)
|
|
|
+ end).
|
|
|
+```
|
|
|
+
|
|
|
+
|
|
|
+## Keep Alive
|
|
|
+
|
|
|
+Иногда соединение с базой данных может оборваться, причем клиентская
|
|
|
+сторона (epgsql драйвер), может об этом и не знать. В этом случае
|
|
|
+запросы, проходящие через это соединение, будут завершаться с ошибкой
|
|
|
+{error, timeout}. Если не восстановить соединение, то в пуле
|
|
|
+окажется процесс (или несколько процессов), неспособный выполнять
|
|
|
+запросы.
|
|
|
+
|
|
|
+Поэтому каждый процесс в пуле мониторит состояние своего соединения,
|
|
|
+периодически отправляя keep-alive запросы (на самом деле это запросы
|
|
|
+"SELECT 1"). Если в течение определенного времени на такой запрос не
|
|
|
+приходит ответ от базы данных, то соединение считается потерянным, и
|
|
|
+процесс устанавливает его заново.
|
|
|
+
|
|
|
+Все это происходит внутри библиотеки, незаметно для пользователя.
|
|
|
+Но может потребоваться настройка интервала, через которые посылаются
|
|
|
+запросы (по умолчанию 60 секунд).
|
|
|
+
|
|
|
+В текущей версии библиотеки не предусмотрена возможность отключить
|
|
|
+keep-alive. Но можно установить очень долгий интервал. Планируется
|
|
|
+добавить такую настройку.
|
|
|
+
|
|
|
+
|
|
|
+## Reconnect
|
|
|
+
|
|
|
+В некоторых случаях **epgsql_pool:query** может вернуть {error, reconnecting}.
|
|
|
+Это значит, процесс потерял соединение с базой и пытается его восстановить.
|
|
|
+
|
|
|
+Попытки установить соединение реализованы с exponential backoff, с
|
|
|
+увеличением интервала между попытками от 100 миллисекунд до 5
|
|
|
+секунд. Число попыток не ограничено. Эти интервалы настраиваются.
|
|
|
+
|
|
|
+Можно попытаться повторить вызов **epgsql_pool:query**. Скорее всего из пула
|
|
|
+будет получен другой процесс, и он сможет выполнить запрос.
|
|
|
+
|
|
|
+
|
|
|
+## Настройки
|
|
|
+
|
|
|
+Библиотека позволяет конфигурировать ряд параметров, касающихся работы пула,
|
|
|
+и различных интервалов.
|
|
|
+
|
|
|
+Все доступные параметры можно получить вызовом **epgsql_pool:get_settings/0**:
|
|
|
+
|
|
|
+```
|
|
|
+3> epgsql_pool:get_settings().
|
|
|
+ #{connection_timeout => 10000,
|
|
|
+ keep_alive_timeout => 60000,
|
|
|
+ max_reconnect_timeout => 5000,
|
|
|
+ min_reconnect_timeout => 100,
|
|
|
+ pooler_get_worker_timeout => 10000,
|
|
|
+ pooler_max_queue => 100,
|
|
|
+ query_timeout => 10000}
|
|
|
+```
|
|
|
+
|
|
|
+И можно установить новые значения вызовом **epgsql_pool:set_settings/1**:
|
|
|
+
|
|
|
+```
|
|
|
+3> epgsql_pool:set_settings(
|
|
|
+ #{keep_alive_timeout => 24 * 3600 * 1000,
|
|
|
+ query_timeout => 60000}).
|
|
|
+```
|
|
|
+
|
|
|
+При этом в map можно указать только те параметры, которые вы ходите поменять.
|
|
|
+
|
|
|
+Доступны следующие настройки:
|
|
|
|
|
|
-## keep-alive
|
|
|
+**connection_timeout** -- timeout на установку соединения для драйвера epgsql.
|
|
|
+По умолчанию 10000 миллисекунд.
|
|
|
|
|
|
-TODO
|
|
|
+**keep_alive_timeout** -- с таким интервалом посылаются запросы keep alive.
|
|
|
+По умолчанию 60000 миллисекунд
|
|
|
|
|
|
-## reconnect
|
|
|
+**max_reconnect_timeout** и **min_reconnect_timeout** -- exponential backoff параметры
|
|
|
+для восстановления соединения. Интервал между попытками восстановления начинается
|
|
|
+с **min_reconnect_timeout** и экспоненциально растет после каждой попытки
|
|
|
+до **max_reconnect_timeout**. По умолчанию 5000 и 100 миллисекунд.
|
|
|
|
|
|
-TODO
|
|
|
-with exponential backoff
|
|
|
+**pooler_get_worker_timeout** -- timeout на получение процесса из пула.
|
|
|
+Если в пуле нет свободных процессов, и они не появились за это время,
|
|
|
+то epgsql\_pool:query вернет {error, pool\_overload}
|
|
|
+По умолчанию 10000 миллисекунд.
|
|
|
|
|
|
-## настройки
|
|
|
+**pooler_max_queue** -- размер очереди запросов на получение процесса из пула.
|
|
|
+Если запросов будет больше, то epgsql\_pool:query вернет {error, pool\_overload}.
|
|
|
+По умолчанию 100 запросов.
|
|
|
|
|
|
-TODO
|
|
|
+**query_timeout** -- timeout на время выполнения запроса к базе. Действует
|
|
|
+для всех запросов, кроме тех, где timeout явно переопределен.
|
|
|
+Смотрите раздел **Запрос к базе данных** выше. По умолчанию 10000 миллисекунд.
|
|
|
|
|
|
-get_settings
|
|
|
-set_settings
|
|
|
+Значения по умолчанию могут измениться в новых версиях библиотеки.
|