Files
speckle-server/packages/ifc-import-service/src/ifc_importer/repository.py
T

77 lines
2.2 KiB
Python

import json
from asyncpg import Connection, connect
from ifc_importer.config import settings
from ifc_importer.domain import FileimportJob, JobStatus
async def setup_connection() -> Connection:
connection = await connect(settings.fileimport_queue_postgres_url)
await connection.set_type_codec(
"jsonb",
encoder=json.dumps,
decoder=json.loads,
schema="pg_catalog",
)
return connection
async def get_next_job(connection: Connection) -> FileimportJob | None:
"""Get a fileimport job from the connection."""
job = await connection.fetchrow(
"""
WITH next_job AS (
UPDATE background_jobs
SET
"attempt" = "attempt" + 1,
"status" = $1,
"updatedAt" = NOW()
WHERE id = (
SELECT id FROM background_jobs
WHERE ( --queued job
payload ->> 'fileType' = 'ifc'
AND status = $2
AND "attempt" < "maxAttempt"
)
OR ( --timed job left on processing state
payload ->> 'fileType' = 'ifc'
AND status = $1
AND "updatedAt" < NOW() - ("timeoutMs" * interval '1 millisecond')
)
ORDER BY "createdAt"
FOR UPDATE SKIP LOCKED
LIMIT 1
)
RETURNING *
)
SELECT * FROM next_job;
""",
JobStatus.PROCESSING.value,
JobStatus.QUEUED.value,
)
if not job:
return None
return FileimportJob.model_validate(dict(job))
async def return_job_to_queued(connection: Connection, job_id: str) -> None:
print(f"returning job: {job_id} to queued")
return await set_job_status(connection, job_id, JobStatus.QUEUED)
async def set_job_status(
connection: Connection, job_id: str, job_status: JobStatus
) -> None:
print(f"updating job: {job_id}'s status to {job_status}")
_ = await connection.execute(
"""
UPDATE background_jobs
SET status = $1, "updatedAt" = NOW()
WHERE id = $2
""",
job_status.value,
job_id,
)