Para preparar el programador de tareas asíncrono, necesitamos los propios
postgres y su extensión
pg_task . (Le di enlaces a mis postgres de fork, porque hice algunos cambios que aún no se han podido incluir en el repositorio original. También puede usar la imagen
preparada ).
(Hay un error en PL / pgSQL en el PostgreSQL original, debido a que mi programador no funciona correctamente cuando ocurre una excepción no detectada en una tarea escrita en PL / pgSQL. Describí este error
aquí y lo arreglé en mi tenedor
aquí ).
Para instalar el programador, no necesita crear una extensión en (cada) base de datos. En cambio, solo agréguelo al archivo de configuración
shared_preload_libraries = 'pg_task'
Después de reiniciar PostgreSQL, el planificador creará tablas de tareas en todas las bases de datos en nombre de los usuarios de la base de datos y en los esquemas predeterminados para estos usuarios.
Si desea que el planificador se ejecute solo para bases de datos específicas, puede especificarlas en el archivo de configuración
pg_task.database = 'database1,database2'
Si desea ejecutar el planificador no desde los usuarios de la base de datos, esto también se puede configurar como
pg_task.database = 'database1:user1,database2:user2'
Si necesita crear tablas de planificador que no estén en el esquema predeterminado para los usuarios, puede configurarlo así
pg_task_schema.database1 = schema3
Si también necesita nombrar la tabla del planificador de manera diferente, puede hacerlo así
pg_task_table.database1 = table3
Por defecto, el planificador verifica las tareas cada 1000 ms, pero esto se puede cambiar de la siguiente manera
pg_task_period.database1 = 100 pg_task_period.database2 = 10
Entonces, el planificador crea (si no se ha creado) (un esquema, si es necesario, y) una tabla de tareas con tales columnas
id BIGSERIAL NOT NULL PRIMARY KEY,
De hecho, el planificador inicia varios flujos de trabajo en segundo plano: uno para rastrear los cambios en el archivo de configuración e iniciar / detener, si es necesario, los otros procesos en segundo plano del planificador. Y un flujo de trabajo en segundo plano para cada base de datos para verificar las tareas programadas en cada base de datos e iniciar tareas si es necesario.
Por ejemplo, si queremos completar la tarea lo más rápido posible, entonces ejecutamos el comando SQL
INSERT INTO task (request) VALUES ('SELECT now()')
El planificador escribe el resultado de la tarea en la columna de resultados en forma de texto. Si como resultado de la ejecución de la tarea hay varias columnas, el planificador las agregará al encabezado junto con los tipos de columna. Además, como resultado de la tarea, puede haber varias líneas, todas ellas se agregarán a la columna de resultados.
Si queremos completar una tarea, por ejemplo, después de 5 minutos, entonces escribimos el tiempo planificado en la columna correspondiente
INSERT INTO task (dt, request) VALUES (now() + '5 min':INTERVAL, 'SELECT now()')
y si queremos que la tarea se complete en un momento específico, la anotaremos
INSERT INTO task (dt, request) VALUES ('2019-07-01 00:00:00', 'SELECT now()')
Si necesitamos que la tarea se realice cada 5 minutos, entonces escribimos así
INSERT INTO task (repeat, request) VALUES ('5 min', 'SELECT now()')
si es así escribe
INSERT INTO task (repeat, request, drift) VALUES ('5 min', 'SELECT now()', false)
entonces la tarea se repetirá 5 minutos después de la finalización de la tarea (y no después de la hora programada, como por defecto).
Si se produce una excepción durante la ejecución de una tarea, se intercepta y se escribe en forma de texto en la columna de resultados, y se asigna el estado correspondiente a la tarea.
Por ejemplo
INSERT INTO task (request) VALUES ('SELECT 1/0')
Si es necesario que para una cola de tareas no se ejecuten más de 2 tareas simultáneamente, entonces creamos tareas mediante el comando
INSERT INTO task (queue, max, request) VALUES ('queue', 2, 'SELECT now()')
Supongamos que en esta cola hemos acumulado muchas tareas y que son ejecutadas simultáneamente por 2. Si crea una tarea por
INSERT INTO task (queue, max, request) VALUES ('queue', 3, 'SELECT now()')
entonces se ejecutará tan pronto como sea posible de todas las demás tareas en esta cola, es decir sigue siendo algo como prioridad