Cron job là chương trình để chạy các tác vụ lặp đi lặp lại theo chu kỳ nhất định.

Hôm nay chúng ta sẽ tìm hiểu cách cài đặt extension cron trong postgresql trên môi trường docker và chạy thử.

1. Cấu trúc thư mục

├── postgres
|   ├── init-db
|      └── pg_cron.sh
|   ├── Dockerfile
├── docker-compose.yaml

2. Dockerfile

FROM postgres:latest

## Cài đặt git, các lệnh build (như make) và postgres
RUN apt-get update && apt-get -y install git build-essential postgresql-server-dev-14

## clone repo pg_cron
RUN git clone https://github.com/citusdata/pg_cron.git
## cd vào repo và install
RUN cd pg_cron && make && make install

## Sau khi install xong thì xóa repo lẫn các thư viện vừa cài đặt trên
RUN cd / && \
        rm -rf /pg_cron && \
        apt-get remove -y git build-essential postgresql-server-dev-14 && \
        apt-get autoremove --purge -y && \
        apt-get clean && \
        apt-get purge

## Copy folder chứa file pg_cron.sh chứa các chuỗi lệnh để chạy trước khi khởi chạy server postgres
COPY ./init-db /docker-entrypoint-initdb.d

3. pg_cron.sh

customconf=/var/lib/postgresql/data/postgresql.conf

//Load pg_cron lúc khởi chạy postgre
echo "shared_preload_libraries = 'pg_cron'" >> $customconf

//Xác định database mà pg_cron chạy trên đấy, đọc ở biến môi trường
echo "cron.database_name = '$POSTGRES_DB'" >> $customconf

4. docker-compose.yaml

version: "3.8"

volumes:
  db_vol:

services:
  postgres:
    image: database
    build:
      context: ./postgres
      dockerfile: Dockerfile
    volumes:
      - db_vol:/var/lib/postgresql/data
    ports:
      - 5433:5432
    environment:
      POSTGRES_PASSWORD: 123
      POSTGRES_DB: postgres
      POSTGRES_USER: postgres

5. Khởi động

Mở terminal chạy lệnh sau

docker-compose up -d

Sau khi build xong, ta bắt đầu kết nối vào container postgres.

Sau đó chạy các lệnh sql sau

Create extension pg_cron;

Create table users (
   id serial,
   name text
);

6. Bài tập:

Giờ ta sẽ thử làm một bài tập: Mỗi 1 phút trôi qua, insert vào bảng users một name ngẫu nhiên trong mảng gồm 5 giá trị name.

/*
 Khởi tạo tác vụ định kỳ bằng cách chạy function schedule
 */
SELECT cron.schedule('insert-name', '* * * * *',$$
   Insert into users (name) values (
      	(Array['Alice', 'Bob', 'John', 'Jane', 'Smith'])[floor ( 10 * random() / 2)]
   )
$$);

Sau khi chạy function, ta thử kiểm tra bảng cron.job

Select * from cron.job

Kết quả:

jobidschedulecommandnodenamenodeportdatabaseusernameactivejobname
1* * * * *Insert into users (name) values …localhost5432postgrespostgrestrueinsert-name

Giờ ta chờ mỗi phút và kiểm tra xem bảng users đã insert dữ liệu hay chưa. Đây là kết quả sau 3 phút

SELECT * FROM users;

Kết quả:

idname
1John
2Bob
3Jane

Để từ bỏ tác vụ trên, ta có thể sử dụng function unschedule(jobid) hay unschedule(jobname)

SELECT cron.unschedule(1)
//hoặc
SELECT cron.unschedule('insert-name')

Kiểm tra bảng cron.job:

jobidschedulecommandnodenamenodeportdatabaseusernameactivejobname

Kết

Như vậy trong bài này ta đã biết cách để chạy tác vụ định kỳ trên postgres khởi động bằng docker. Đây là tiện ích có thể áp dụng cho rất nhiều tình huống trong đời sống cần chạy tác vụ định kỳ, ví dụ như cuối tháng tính lương cho nhân viên,…