Control the way synchronous calls to defer are handled¶
When your app is synchronous (see Asynchronous operations & concurrency), you may want to defer tasks synchronously. In most cases, if you set up an asynchronous connector, Procrastinate will automatically select the right connector for you. However, you can also explicitly set up a synchronous connector.
SyncPsycopgConnector
¶
By setting your App
’s connector to an instance of SyncPsycopgConnector
(or
any other synchronous connector), you will get “classic” synchronous I/O. Note
that in this case, the only thing you’ll be able to do is defer tasks. Other
operations trigger an error with a synchronous connector.
import procrastinate
app = procrastinate.App(
connector=procrastinate.SyncPsycopgConnector(
host="somehost",
),
)
SyncPsycopgConnector
uses a psycopg_pool.ConnectionPool
(see psycopg
documentation).
Psycopg2Connector
¶
The Psycopg2Connector
is a connector that uses a
psycopg2_pool.ThreadedConnectionPool
. It used to be the default connector,
but SyncPsycopgConnector
is now the preferred option. There is no plan to
deprecate Psycopg2Connector
.
SQLAlchemyPsycopg2Connector
¶
If you use SQLAlchemy in your synchronous application, you may want to use an
SQLAlchemyPsycopg2Connector
from the contrib.sqlalchemy
module instead. The
advantage over using a Psycopg2Connector
is that Procrastinate can use the same
SQLAchemy engine (and connection pool) as the rest of your application, thereby
minimizing the number of database connections.
from sqlalchemy import create_engine
from procrastinate import App
from procrastinate.contrib.sqlalchemy import SQLAlchemyPsycopg2Connector
engine = create_engine("postgresql+psycopg2://", echo=True)
app = App(connector=SQLAlchemyPsycopg2Connector())
app.open(engine)
Procrastinate’s automatic connector selection¶
Async connectors are able to summon their synchronous counterpart when needed
(using BaseConnector.get_sync_connector
).
All sync operations in Procrastinate (so mainly deferring tasks synchronously) will request the synchronous connector from the async connector under the hood.
Note
If you’re relying on this mechanism, note the following mechanism:
If you request the synchronous connector before opening the app, you will be using a synchronous connector.
If you request the synchronous connector after opening the app, you will get
the asynchronous connector, with a compatibility layer to make synchronous
operations. This will only work if you call it inside a function decorated
with asgiref.sync.sync_to_async
(such as inside a sync job). Otherwise,
you will likely get a RuntimeError
.