# erlang_test Реализовать приложение для вызова событий по времени. Приложение должно работать с относительной и абсолютной величинами таймингов 1. Текущее время + относительная часть (например 30 сек) 2. Абсолютная (сработать, например, 01.01.2016) Приложение должно иметь протокол: 1. для приема заявок. Входные параметры: * ID задачи (varchar) * ID процесса (integer) * тип(статика/динамика) * время(integer) 2. для удаления событий. Входные параметры: * ID задачи (varchar) * ID процесса (integer) При приеме нового события с одним и тем же (ID задачи, ID процесса) прошлый нужно перезатирать. При удалении события вызываться при срабатывании time оно уже не должно. Общение с основным приложением будет на уровне очереди(rabbitMQ), при срабатывании события необходимо бросить в очередь rabbitMQ событие (в спецификации очереди есть параметр reply-to, который укажет в какую очередь отправить ответ), куда включить ID задачи и ID процесса (для примера {call_timer, ProcID, TaskID}). Для экономии памяти необходима гибридная схема: храним N задач по процессу, остальное в базе. Когда очередь задач по процессу иссякла, идем в базу и набираем еще порцию данных. Для уменьшения запросов в БД необходимо агрегировать запросы в базу (чтобы не случилось так, что 1000 обработчиков захотели получить данные в единицу времени). Приложение должно с легкостью управляться с нагрузкой - 20тысяч приемов новых заявок и 20 тысяч удалений в секунду одновременно. Время срабатывания события критично до секунды. Выполнять задание в репозитории типа github. Использовать тесты. Задание можно полностью не сделать. Важен подход и оформление кода. --- Q: тобто в одну секунду йдуть і 20k нових, і ще 20k видалення існуючих? просто 20k нових та 20k спрацювань не рахується? A: приходят заявки на выполнение через 5 секунд, часть из них отменяется ( удаление ) получается да, одновременно --- ``` $ make $ make start ERL_LIBS="apps:deps" erl +pc unicode -args_file vm.args -config sys.config -eval 'application:start(myapp)' Erlang/OTP 23 [erts-11.2.2.4] [source] [64-bit] [smp:4:4] [ds:4:4:10] [async-threads:5] [hipe] Eshell V11.2.2.4 (abort with ^G) (myapp@127.0.0.1)1> test:test(). ok (myapp@127.0.0.1)2> update: "12" 12 update: "13" 13 deleted: "9" 9 deleted: "14" 14 tick: "1" 1 tick: "3" 3 tick: "5" 5 tick: "7" 7 tick: "2" 2 tick: "4" 4 tick: "11" 11 tick: "6" 6 tick: "8" 8 tick: "15" 15 tick: "10" 10 tick: "12" 12 tick: "13" 13 % gen_server:cast add/delete (myapp@127.0.0.1)2> test:testn(300). ok 57 59 57 57 48 58 62 41 61 49 44 52 47 64 53 48 42 51 59 58 47 44 60 58 52 60 ... "the end" % gen_server:call add/delete (myapp@127.0.0.1)3> test:testn_b(300). ok 238 236 221 282 236 224 228 234 357 228 356 235 228 225 224 237 232 236 239 233 243 247 258 247 ... "the end" ``` --- postgresql 14 ``` sudo -u postgres psql CREATE DATABASE test_database; CREATE USER test_user WITH password 'qwerty'; GRANT ALL ON DATABASE test_database TO test_user; \q ``` ``` sudo vim /etc/postgresql/14/main/postgresql.conf max_connections = 200 sudo service postgresql restart ``` ``` CREATE TABLE "events_table" ( "id" bigserial, "task_id" varchar(255) NOT NULL, "proc_id" integer NOT NULL, "time" integer NOT NULL, "deleted" smallint DEFAULT NULL, --active: NULL, deleted: 1 PRIMARY KEY ("id") ); CREATE UNIQUE INDEX events_table_ids_uniq ON events_table (task_id, proc_id); ALTER TABLE events_table ADD CONSTRAINT events_table_ids_uniq UNIQUE USING INDEX events_table_ids_uniq; CREATE INDEX events_table_deleted_idx ON events_table (deleted); -- truncate events_table; -- ALTER SEQUENCE events_table_id_seq RESTART WITH 1; ``` ### deps ``` https://github.com/epgsql/epgsql/tree/4.5.0 https://github.com/seth/pooler/tree/9c28fb479f9329e2a1644565a632bc222780f1b7 https://github.com/wgnet/herd/tree/1.3.4 https://github.com/wgnet/epgsql_pool/tree/1.4.4 ```