La idea es que juando una tarea termine, espere dos minuto y se vuelva a ejecutar.
El problema es que la duración de la tarea es variable y la replanificación debe hacerse en cuanto termine. Sea la hora que sea, que se ejecute dos minutos después.
Para ello, manejar el intérvalo de ejecución para calcular el momento siguiente no es buena idea, porque el valor de la siguiente ejecución se determina en el momento en el que el job empieza a ejecutarse, por lo que para crear esta cadena de ejecuciones en serie debemos modificar el START_DATE.
Voy a crear un procedimiento que se llame «DUERME_TIEMPO», en el que el proceso dormirá una cantidad de segundos variable entre cero y tres minutos. Para registrar el inicio y el fin del procedimiento, registraré el timestamp en una tabla EJECUCION para los valores de EMPEZAR A DORMIR (se ejecuta el sleep) y SE DESPIERTA (finaliza el sleep).
create table ejecucion (estado varchar2(20),tiempo timestamp); create or replace procedure duerme_tiempo is begin -- registramos el inicio insert into ejecucion values ('EMPIEZA A DORMIR',systimestamp); commit; -- el proceso duerme por un tiempo random entre cero y 3 minutos dbms_session.sleep(mod(abs(dbms_random.random),180)); -- registramos cuando termina la ejecución insert into ejecucion values ('SE DESPIERTA',systimestamp); commit; end; /
De modo que cada ejecución deje este log registrado.
SQL> exec duerme_tiempo; Procedimiento PL/SQL terminado correctamente. Transcurrido: 00:01:19.02 SQL> select * from ejecucion; ESTADO -------------------- TIEMPO --------------------------------------------------------------------------- EMPIEZA A DORMIR 28/11/24 07:56:23,964952 SE DESPIERTA 28/11/24 07:57:42,979512
Para planificar su ejecución, voy a crear un job llamado DUERME_Y_DESPIERTA para que empiece en cuanto se habilite e inmediatamente después ejecute DUERME_TIEMPO en el inicio de minuto.
La frecuencia de intérvalos es, por tanto, ejecuciones de a cada minuto, cuando coincida el segundo cero. Esto es algo adicional, para hacer que los procesos empiecen siempre después de dos minutos del fin de su ejecución pero al inicio del minuto siguiente. Lo hago solamente para ver los instantes precisos de inicio del job que coincidan con un minuto exacto. Si queremos ser fieles a la ejecución exacta tras dos minutos de terminar la ejecución anterior, quitaríamos el parámetro «bysecond=0;».
begin dbms_scheduler.create_job ( job_name => 'duerme_y_despierta', job_type => 'plsql_block', job_action => 'begin duerme_tiempo; end;', start_date => systimestamp, repeat_interval => 'freq=minutely; bysecond=0;', enabled => false); end; / PL/SQL procedure successfully completed.
Ahora el job está creado, pero no está activo. Esto es porque antes de activarlo, debemos modificar el procedure para que, al finalizar la ejecución, modifique el job DUERME_Y_DESPIERTA para que inicie dos minutos después.
Exactamente dos minutos después, cuando llegue al segundo «00». Es decir, cuando inicie el siguiente minuto.
create or replace procedure duerme_tiempo is begin -- registramos el inicio insert into ejecucion values ('EMPIEZA A DORMIR',systimestamp); commit; -- el proceso duerme por un tiempo random entre cero y 3 minutos dbms_session.sleep(mod(abs(dbms_random.random),180)); -- registramos cuando termina la ejecución insert into ejecucion values ('SE DESPIERTA',systimestamp); commit; -- Se programa el job para ejecutarse 2 minutos despues dbms_scheduler.set_attribute ( name => 'duerme_y_despierta', attribute => 'start_date', value => sysdate+(2/24/60)); end; /
En este momento ya podemos habilitar el job, y éste se ejecutará instantáneamente, y cada ejecución posterior se replanificará al vuelo independiente del tiempo que tarde.
SQL> select * from ejecucion; ESTADO TIEMPO -------------------- --------------------------------------------------------------------------- EMPIEZA A DORMIR 28-NOV-24 11.15.01.001800 AM SE DESPIERTA 28-NOV-24 11.16.39.064239 AM --> 1 minuto y 38 segundos después EMPIEZA A DORMIR 28-NOV-24 11.19.00.185823 AM --> 2 minutos y 21 segundos después (11:19 exacta) SE DESPIERTA 28-NOV-24 11.19.41.334749 AM --> 41 segundos después EMPIEZA A DORMIR 28-NOV-24 11.22.00.129578 AM --> 2 minutos y 19 segundos después (11:22 exacta) SE DESPIERTA 28-NOV-24 11.22.10.134432 AM EMPIEZA A DORMIR 28-NOV-24 11.25.00.075948 AM SE DESPIERTA 28-NOV-24 11.25.45.366549 AM EMPIEZA A DORMIR 28-NOV-24 11.28.00.024666 AM SE DESPIERTA 28-NOV-24 11.30.57.174717 AM EMPIEZA A DORMIR 28-NOV-24 11.33.00.029588 AM SE DESPIERTA 28-NOV-24 11.33.29.240348 AM EMPIEZA A DORMIR 28-NOV-24 11.36.00.199082 AM SE DESPIERTA 28-NOV-24 11.37.53.430395 AM