Search code examples
postgresqlpython-2.7plpython

time.sleep() has 60 sec limit in plpythonu?


Note: I'm running Postgres 11.7 and Python 2.7.17.

It appears that time.sleep() has 60 sec limit in plpythonu function. It works as expected up to 60 seconds. But if passed a value greater than 60 then it stops at 60 seconds.

CREATE OR REPLACE FUNCTION test_sleep(interval_str INTERVAL)
    RETURNS INTERVAL
AS $$
    try:
        import time
        import datetime

        start_time = time.time()
        t = datetime.datetime.strptime(interval_str,"%H:%M:%S")
        tdelta = datetime.timedelta(hours=t.hour, minutes=t.minute, seconds=t.second)
        interval_secs = tdelta.total_seconds()
        print 'interval_secs=%s' % repr(interval_secs)
        time.sleep(interval_secs)
        elapsed_secs = time.time() - start_time
        return datetime.timedelta(seconds=elapsed_secs)
    except:
        import traceback
        print traceback.format_exc()
        raise
$$ LANGUAGE PLPYTHONU;

Here's a test on command line using psql. The first test runs as expected. I told it to sleep for two seconds and it dis. The second test only sleeps for 60 seconds even though I requested a sleep for 120 seconds.

$ echo "select now(), test_sleep('2 sec'); select now();" | psql
             now              |   test_sleep
------------------------------+-----------------
 2021-05-07 11:10:27.63041-04 | 00:00:02.005745
(1 row)

              now
-------------------------------
 2021-05-07 11:10:29.652542-04
(1 row)

$ echo "select now(), test_sleep('2 min'); select now();" | psql
              now              |   test_sleep
-------------------------------+-----------------
 2021-05-07 11:10:36.056578-04 | 00:00:59.977787
(1 row)

              now
-------------------------------
 2021-05-07 11:11:36.050637-04
(1 row)

$ 

Here's output from the Postgres log file.

interval_secs=2.0
interval_secs=120.0

Solution

  • This is not unexpected (although I can't reliably reproduce it).

    https://realpython.com/python-sleep/

    Note: In Python 3.5, the core developers changed the behavior of time.sleep() slightly. The new Python sleep() system call will last at least the number of seconds you’ve specified, even if the sleep is interrupted by a signal. This does not apply if the signal itself raises an exception, however.

    So in python2, time.sleep can return early if interrupted by a signal. If you don't like that, have it loop to sleep again for the remainder of the time.