saq 0.24.11__py3-none-any.whl → 0.24.13__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
saq/__init__.py CHANGED
@@ -14,4 +14,4 @@ __all__ = [
14
14
  "Worker",
15
15
  ]
16
16
 
17
- __version__ = "0.24.11"
17
+ __version__ = "0.24.13"
saq/queue/postgres.py CHANGED
@@ -21,7 +21,7 @@ from saq.job import (
21
21
  from saq.multiplexer import Multiplexer
22
22
  from saq.queue.base import Queue, logger
23
23
  from saq.queue.postgres_migrations import get_migrations
24
- from saq.utils import now_seconds
24
+ from saq.utils import now, now_seconds
25
25
 
26
26
  if t.TYPE_CHECKING:
27
27
  from collections.abc import Iterable
@@ -666,7 +666,7 @@ class PostgresQueue(Queue):
666
666
  UPDATE {jobs_table} SET status = 'active'
667
667
  FROM locked_job
668
668
  WHERE {jobs_table}.key = locked_job.key
669
- RETURNING job, {jobs_table}.key, status
669
+ RETURNING job, {jobs_table}.key
670
670
  """
671
671
  )
672
672
  ).format(
@@ -680,7 +680,22 @@ class PostgresQueue(Queue):
680
680
  "phigh": self._priorities[1],
681
681
  },
682
682
  )
683
- rows = await cursor.fetchall()
683
+
684
+ jobs = []
685
+ keys = []
686
+ dequeued = now()
687
+
688
+ for payload, key in await cursor.fetchall():
689
+ # there can be a race condition where a job is swept right after it is dequeued
690
+ # but before it's updated for processing
691
+ job = self.deserialize(payload, Status.ACTIVE)
692
+ assert job
693
+ job.started = dequeued
694
+ job.touched = dequeued
695
+ await self._update(job, status=Status.ACTIVE, connection=conn)
696
+
697
+ jobs.append(job)
698
+ keys.append(key)
684
699
 
685
700
  await conn.execute(
686
701
  SQL(
@@ -695,20 +710,20 @@ class PostgresQueue(Queue):
695
710
  jobs_table=self.jobs_table,
696
711
  job_lock_keyspace=self.job_lock_keyspace,
697
712
  ),
698
- {"keys": [key for _, key, _ in rows]},
713
+ {"keys": keys},
699
714
  )
700
- lock_acquisition_results = await cursor.fetchall()
701
- for key, lock_acquired in lock_acquisition_results:
715
+
716
+ for key, lock_acquired in await cursor.fetchall():
702
717
  if not lock_acquired:
703
718
  logger.error(
704
719
  "Could not acquire lock for job %s. This may result in unexpected behavior",
705
720
  key,
706
721
  )
707
722
 
708
- for job, _, status in rows:
709
- self._job_queue.put_nowait(self.deserialize(job, status))
723
+ if jobs:
724
+ for job in jobs:
725
+ self._job_queue.put_nowait(job)
710
726
 
711
- if rows:
712
727
  await self._notify(DEQUEUE)
713
728
 
714
729
  async def _enqueue(self, job: Job) -> Job | None:
@@ -873,7 +888,21 @@ class PostgresQueue(Queue):
873
888
 
874
889
  @asynccontextmanager
875
890
  async def _get_dequeue_conn(self) -> t.AsyncGenerator:
891
+ """
892
+ This context manager is used instead of the pool.connection() context manager because we need
893
+ to reuse specific connections outside of a context to properly manager advisory locks.
894
+ If advisory locks are not used, this context manager can be replaced with pool.connection().
895
+ """
876
896
  async with self._connection_lock:
897
+ # Check if the connection is still associated with a connection pool.
898
+ if not getattr(self._dequeue_conn, "_pool", None):
899
+ # The only known case of having a connection without a pool is when the connection was closed
900
+ # Therefore this close check shouldn't be needed but it doesn't hurt to close anyways
901
+ # to cover potential case where the connection is not closed and we would leave an open connection.
902
+ if self._dequeue_conn:
903
+ await self._dequeue_conn.close()
904
+ self._dequeue_conn = None
905
+
877
906
  if self._dequeue_conn:
878
907
  try:
879
908
  # Pool normally performs this check when getting a connection.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: saq
3
- Version: 0.24.11
3
+ Version: 0.24.13
4
4
  Summary: Distributed Python job queue with asyncio and redis
5
5
  Home-page: https://github.com/tobymao/saq
6
6
  Author: Toby Mao
@@ -1,4 +1,4 @@
1
- saq/__init__.py,sha256=su3QNUaQuTeApvIOApyA-tqOHgXQLGx-_WrSLhrDWEg,219
1
+ saq/__init__.py,sha256=n2njj1ekrqBoS5BBfDJRAxeqL4HwEQixcjMOf12TGBc,219
2
2
  saq/__main__.py,sha256=N4RNqnCcj7eZbM3OyYaC03_6Cot-y-SxW5Hwx6fuzKU,2440
3
3
  saq/errors.py,sha256=XPJw6J3caSAho4ZybuodIbeuGjboVabLuf3NFOEE-4Q,112
4
4
  saq/job.py,sha256=X49OuSqZeN-RVmh4AonZRrwk2wU8MeukLSxrvjGLm7E,11552
@@ -10,7 +10,7 @@ saq/worker.py,sha256=W9rqK_u0bbvUbdb879pvf1f-suNnesKk1TjYqHQREc8,16817
10
10
  saq/queue/__init__.py,sha256=5LgBHGylCVvrLDcjMCcI2dRRgh0BPdz2TKOdc8NMs2E,87
11
11
  saq/queue/base.py,sha256=3Fc91Cgrpp1KUTRT0nPL9lroRmPCz7WGFpZkxDyMQh4,15919
12
12
  saq/queue/http.py,sha256=V9S26gJbUt5AUIR2ETasSQy4Q_K30eGtguBYHpfcLGU,7739
13
- saq/queue/postgres.py,sha256=7FSljVrqISV8w82cv0yWvyejMpucbucsjpu8Ntoqee4,35648
13
+ saq/queue/postgres.py,sha256=HP-RKIb6OPa7I4QTrS1omWlDUPvzQRcjaB0ZrxnpYvE,37060
14
14
  saq/queue/postgres_migrations.py,sha256=gI6j-0TzlFFSWxji3Dy9aJ-llboJBm92J4tB_YZ7qI8,2080
15
15
  saq/queue/redis.py,sha256=sa_wzUUlfPw-RZ-v_cnDEJWEFyUi3sy_3YTqG4UklOA,17754
16
16
  saq/web/__init__.py,sha256=NG9LfjgJQxNft0_iZuZ3LnX1I58SfxRwKpycjazBoGE,23
@@ -20,9 +20,9 @@ saq/web/starlette.py,sha256=i38xuNcnQvWBY3jyHHu9Uo9ILSBzOwmk5Bq06c3CQzM,4432
20
20
  saq/web/static/app.js,sha256=i6PaRvBvt96LOINBdEuKkDvVeM-GA8lJiFg4jtQ3viY,7094
21
21
  saq/web/static/pico.min.css.gz,sha256=qCxIv3wWFMQ7MkvGSHQLwxio3121VvvieOkSjw6fv6o,9263
22
22
  saq/web/static/snabbdom.js.gz,sha256=zSO3Z761TB7bYNQFFEtypD0vCuqWesqPJeE5CuV4xRg,7603
23
- saq-0.24.11.dist-info/LICENSE,sha256=p208OXrLf_dMcvuRHpcinfsJdihCqKWbqtFXpw4kyW0,1065
24
- saq-0.24.11.dist-info/METADATA,sha256=IXsF53-LGEvvPVhqPFU6ZFqvH3dNFCaeySLFRCLJHME,7913
25
- saq-0.24.11.dist-info/WHEEL,sha256=tZoeGjtWxWRfdplE7E3d45VPlLNQnvbKiYnx7gwAy8A,92
26
- saq-0.24.11.dist-info/entry_points.txt,sha256=HkKOud1K15_DV7AEltn8G5Ua10VqIgHaZ4BQit4fdOk,42
27
- saq-0.24.11.dist-info/top_level.txt,sha256=FMrrc5EiGr4sQkEDtUMHIpomnWHL9i6xT7B6lvEh8xM,4
28
- saq-0.24.11.dist-info/RECORD,,
23
+ saq-0.24.13.dist-info/LICENSE,sha256=p208OXrLf_dMcvuRHpcinfsJdihCqKWbqtFXpw4kyW0,1065
24
+ saq-0.24.13.dist-info/METADATA,sha256=-tfHuQvVYkcGER_GLb7mCNLAWbRkMM6wdtEa0EIMej0,7913
25
+ saq-0.24.13.dist-info/WHEEL,sha256=tZoeGjtWxWRfdplE7E3d45VPlLNQnvbKiYnx7gwAy8A,92
26
+ saq-0.24.13.dist-info/entry_points.txt,sha256=HkKOud1K15_DV7AEltn8G5Ua10VqIgHaZ4BQit4fdOk,42
27
+ saq-0.24.13.dist-info/top_level.txt,sha256=FMrrc5EiGr4sQkEDtUMHIpomnWHL9i6xT7B6lvEh8xM,4
28
+ saq-0.24.13.dist-info/RECORD,,
File without changes
File without changes