Resep PostgreSQL: Penjadwal Tugas Asinkron

Untuk menyiapkan penjadwal tugas yang tidak sinkron, kita perlu postgres itu sendiri dan ekstensi pg_task . (Saya memberi tautan ke garpu postgres saya, karena saya membuat beberapa perubahan yang belum dijejalkan ke repositori asli. Anda juga dapat menggunakan gambar yang sudah jadi .)

(Ada kesalahan dalam PL / pgSQL di PostgreSQL asli, karena penjadwal saya tidak berfungsi dengan benar ketika pengecualian tanpa tertangkap terjadi dalam tugas yang ditulis dalam PL / pgSQL. Saya menjelaskan kesalahan ini di sini dan memperbaikinya di garpu saya di sini .)

Untuk menginstal penjadwal, Anda tidak perlu membuat ekstensi di (masing-masing) database. Sebagai gantinya, tambahkan saja ke file konfigurasi

shared_preload_libraries = 'pg_task' 

Setelah memulai kembali PostgreSQL, penjadwal akan membuat tabel tugas di semua basis data atas nama pengguna basis data dan dalam skema default untuk pengguna ini.

Jika Anda ingin penjadwal berjalan hanya untuk database tertentu, Anda dapat menentukannya di file konfigurasi

 pg_task.database = 'database1,database2' 

Jika Anda ingin menjalankan penjadwal bukan dari pengguna basis data, maka ini juga dapat ditetapkan sebagai

 pg_task.database = 'database1:user1,database2:user2' 

Jika Anda perlu membuat tabel penjadwal tidak dalam skema default untuk pengguna, Anda dapat mengaturnya seperti ini

 pg_task_schema.database1 = schema3 

Jika Anda juga perlu memberi nama tabel penjadwal secara berbeda, maka Anda dapat melakukannya seperti ini

 pg_task_table.database1 = table3 

Secara default, scheduler memeriksa tugas setiap 1000 ms, tetapi ini dapat diubah sebagai berikut

 pg_task_period.database1 = 100 pg_task_period.database2 = 10 

Jadi, penjadwal membuat (jika belum dibuat) (skema, jika perlu, dan) tabel tugas dengan kolom tersebut

 id BIGSERIAL NOT NULL PRIMARY KEY, -- ,   dt TIMESTAMP NOT NULL DEFAULT NOW(), --     (- -   ) start TIMESTAMP, --     stop TIMESTAMP, --      queue TEXT NOT NULL DEFAULT 'default', --    (      ) max INT, --        (,      ) pid INT, --  ,    request TEXT NOT NULL, --  SQL   response TEXT, --    state TEXT NOT NULL DEFAULT 'QUEUE', --   (- - ,    , , ...) timeout INTERVAL, --      delete BOOLEAN NOT NULL DEFAULT false, --     ,    repeat INTERVAL, --    drift BOOLEAN NOT NULL DEFAULT true --        

Bahkan, penjadwal memulai beberapa alur kerja latar belakang: satu untuk melacak perubahan dalam file konfigurasi dan memulai / menghentikan, jika perlu, proses latar belakang lainnya dari penjadwal. Dan satu alur kerja latar belakang untuk setiap database untuk memeriksa tugas yang dijadwalkan di setiap database dan meluncurkan tugas jika perlu.

Sebagai contoh, jika kita ingin menyelesaikan tugas secepat mungkin, maka kita menjalankan perintah SQL

 INSERT INTO task (request) VALUES ('SELECT now()') 

Penjadwal menulis hasil tugas ke kolom hasil dalam bentuk teks. Jika sebagai hasil dari pelaksanaan tugas ada beberapa kolom, penjadwal akan menambahkannya ke header bersama dengan jenis kolom. Juga, sebagai hasil dari tugas, mungkin ada beberapa baris, semuanya akan ditambahkan ke kolom hasil.

Jika kita ingin menyelesaikan tugas, misalnya, setelah 5 menit, maka kita menulis waktu yang direncanakan di kolom yang sesuai

 INSERT INTO task (dt, request) VALUES (now() + '5 min':INTERVAL, 'SELECT now()') 

dan jika kami ingin tugas diselesaikan pada waktu tertentu, maka kami akan menuliskannya

 INSERT INTO task (dt, request) VALUES ('2019-07-01 00:00:00', 'SELECT now()') 

Jika kita membutuhkan tugas yang harus dilakukan setiap 5 menit, maka kita menulis seperti ini

 INSERT INTO task (repeat, request) VALUES ('5 min', 'SELECT now()') 

jika demikian tulis

 INSERT INTO task (repeat, request, drift) VALUES ('5 min', 'SELECT now()', false) 

maka tugas akan diulangi 5 menit setelah penyelesaian tugas (dan bukan setelah waktu yang dijadwalkan, sebagai default).

Jika pengecualian terjadi selama pelaksanaan tugas, itu dicegat dan ditulis dalam bentuk teks ke kolom hasil, dan negara yang sesuai ditugaskan untuk tugas tersebut.

Sebagai contoh

 INSERT INTO task (request) VALUES ('SELECT 1/0') 

Jika perlu bahwa untuk antrian tugas tidak lebih dari 2 tugas yang dijalankan secara bersamaan, maka kita membuat tugas dengan perintah

 INSERT INTO task (queue, max, request) VALUES ('queue', 2, 'SELECT now()') 

Misalkan kita telah mengumpulkan banyak tugas dalam antrian ini dan mereka secara bersamaan dieksekusi oleh 2. Jika Anda membuat tugas dengan

 INSERT INTO task (queue, max, request) VALUES ('queue', 3, 'SELECT now()') 

maka itu akan dieksekusi sesegera mungkin dari semua tugas lain dalam antrian ini, yaitu itu masih seperti prioritas

Source: https://habr.com/ru/post/id456722/


All Articles