Skip to content

Commit 536051c

Browse files
authored
Reorganize sqlc code somewhat and get it generating again (#21)
Move sqlc-related code into a subdirectory exclusively earmarked for it, bring it an `sqlc.yaml`, remove the unused queries from the file, regenerate code, and start checking code in CI. This will be useful in case we ever need to make modifications to schema or queries for future changes.
1 parent a042415 commit 536051c

File tree

15 files changed

+388
-2236
lines changed

15 files changed

+388
-2236
lines changed

.github/workflows/ci.yaml

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -135,3 +135,33 @@ jobs:
135135

136136
- name: Type check
137137
run: make type-check
138+
139+
sqlc_generates:
140+
runs-on: ubuntu-latest
141+
timeout-minutes: 2
142+
143+
env:
144+
BIN_PATH: /home/runner/bin
145+
SQLC_VERSION: 1.25.0
146+
147+
steps:
148+
- name: Checkout
149+
uses: actions/checkout@v4
150+
151+
- name: Create BIN_PATH and add to PATH
152+
run: |
153+
mkdir -p "$BIN_PATH"
154+
echo "$BIN_PATH" >> $GITHUB_PATH
155+
156+
- name: Install sqlc
157+
run: |
158+
curl -L https://github.com/kyleconroy/sqlc/releases/download/v${{ env.SQLC_VERSION }}/sqlc_${{ env.SQLC_VERSION }}_linux_amd64.tar.gz | tar -xz -C $BIN_PATH
159+
chmod +x $BIN_PATH/sqlc
160+
161+
- name: Generate sqlc
162+
run: make generate/sqlc
163+
164+
- name: Run sqlc diff
165+
run: |
166+
echo "Please make sure that all sqlc changes are checked in!"
167+
git diff --exit-code

Makefile

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,14 @@ help: ## Print this message
1010
fmt: ## Autoformat code with Rye/Ruff
1111
rye fmt
1212

13+
.PHONY: generate
14+
generate: ## Produce all generated artifacts
15+
generate: generate/sqlc
16+
17+
.PHONY: generate/sqlc
18+
generate/sqlc: ## Generate sqlc code
19+
cd src/riverqueue/driver/riversqlalchemy/dbsqlc && sqlc generate
20+
1321
.PHONY: lint
1422
lint: ## Run linter with Rye/Ruff
1523
rye lint
@@ -21,3 +29,11 @@ test: ## Run test suite with Rye/pytest
2129
.PHONY: type-check
2230
type-check: ## Run type check with MyPy
2331
rye run mypy -p riverqueue -p examples -p tests
32+
33+
.PHONY: verify
34+
verify: ## Verify all generated artifacts
35+
verify: verify/sqlc
36+
37+
.PHONY: verify/sqlc
38+
verify/sqlc: # Verify sqlc code
39+
cd src/riverqueue/driver/riversqlalchemy/dbsqlc && sqlc verify

docs/development.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,12 @@ $ rye fmt
6262

6363
Rye uses [Ruff](https://github.com/astral-sh/ruff) under the hood for code formatting.
6464

65+
## Generate sqlc code
66+
67+
```shell
68+
$ make generate
69+
```
70+
6571
## Publish package
6672

6773
1. Pull existing `master` and tags, choose a version, and create a branch:

pyproject.toml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,3 +39,6 @@ allow-direct-references = true
3939

4040
[tool.hatch.build.targets.wheel]
4141
packages = ["src/riverqueue"]
42+
43+
[tool.ruff]
44+
exclude = ["./src/riverqueue/driver/riversqlalchemy/dbsqlc"]

src/riverqueue/driver/driver_protocol.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ class GetParams:
2828
class JobInsertParams:
2929
kind: str
3030
args: Optional[Any] = None
31+
created_at: Optional[datetime] = None
3132
finalized_at: Optional[datetime] = None
3233
metadata: Optional[Any] = None
3334
max_attempts: Optional[int] = field(default=25)

src/riverqueue/driver/riversqlalchemy/models.py renamed to src/riverqueue/driver/riversqlalchemy/dbsqlc/models.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# Code generated by sqlc. DO NOT EDIT.
22
# versions:
3-
# sqlc v1.26.0
3+
# sqlc v1.25.0
44
import dataclasses
55
import datetime
66
import enum

src/riverqueue/driver/riversqlalchemy/pg_misc.py renamed to src/riverqueue/driver/riversqlalchemy/dbsqlc/pg_misc.py

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,17 @@
11
# Code generated by sqlc. DO NOT EDIT.
22
# versions:
3-
# sqlc v1.26.0
3+
# sqlc v1.25.0
44
# source: pg_misc.sql
5+
from typing import Any
6+
57
import sqlalchemy
68
import sqlalchemy.ext.asyncio
79

10+
from . import models
11+
812

913
PG_ADVISORY_XACT_LOCK = """-- name: pg_advisory_xact_lock \\:exec
10-
SELECT
11-
pg_advisory_xact_lock(:p1)
14+
SELECT pg_advisory_xact_lock(:p1)
1215
"""
1316

1417

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
-- name: PGAdvisoryXactLock :exec
2+
SELECT pg_advisory_xact_lock(@key);
Lines changed: 229 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,229 @@
1+
# Code generated by sqlc. DO NOT EDIT.
2+
# versions:
3+
# sqlc v1.25.0
4+
# source: river_job.sql
5+
import dataclasses
6+
import datetime
7+
from typing import Any, List, Optional
8+
9+
import sqlalchemy
10+
import sqlalchemy.ext.asyncio
11+
12+
from . import models
13+
14+
15+
JOB_GET_BY_KIND_AND_UNIQUE_PROPERTIES = """-- name: job_get_by_kind_and_unique_properties \\:one
16+
SELECT id, args, attempt, attempted_at, attempted_by, created_at, errors, finalized_at, kind, max_attempts, metadata, priority, queue, state, scheduled_at, tags
17+
FROM river_job
18+
WHERE kind = :p1
19+
AND CASE WHEN :p2\\:\\:boolean THEN args = :p3 ELSE true END
20+
AND CASE WHEN :p4\\:\\:boolean THEN tstzrange(:p5\\:\\:timestamptz, :p6\\:\\:timestamptz, '[)') @> created_at ELSE true END
21+
AND CASE WHEN :p7\\:\\:boolean THEN queue = :p8 ELSE true END
22+
AND CASE WHEN :p9\\:\\:boolean THEN state\\:\\:text = any(:p10\\:\\:text[]) ELSE true END
23+
"""
24+
25+
26+
@dataclasses.dataclass()
27+
class JobGetByKindAndUniquePropertiesParams:
28+
kind: str
29+
by_args: bool
30+
args: Any
31+
by_created_at: bool
32+
created_at_begin: datetime.datetime
33+
created_at_end: datetime.datetime
34+
by_queue: bool
35+
queue: str
36+
by_state: bool
37+
state: List[str]
38+
39+
40+
JOB_INSERT_FAST = """-- name: job_insert_fast \\:one
41+
INSERT INTO river_job(
42+
args,
43+
created_at,
44+
finalized_at,
45+
kind,
46+
max_attempts,
47+
metadata,
48+
priority,
49+
queue,
50+
scheduled_at,
51+
state,
52+
tags
53+
) VALUES (
54+
:p1\\:\\:jsonb,
55+
coalesce(:p2\\:\\:timestamptz, now()),
56+
:p3,
57+
:p4\\:\\:text,
58+
:p5\\:\\:smallint,
59+
coalesce(:p6\\:\\:jsonb, '{}'),
60+
:p7\\:\\:smallint,
61+
:p8\\:\\:text,
62+
coalesce(:p9\\:\\:timestamptz, now()),
63+
:p10\\:\\:river_job_state,
64+
coalesce(:p11\\:\\:varchar(255)[], '{}')
65+
) RETURNING id, args, attempt, attempted_at, attempted_by, created_at, errors, finalized_at, kind, max_attempts, metadata, priority, queue, state, scheduled_at, tags
66+
"""
67+
68+
69+
@dataclasses.dataclass()
70+
class JobInsertFastParams:
71+
args: Any
72+
created_at: Optional[datetime.datetime]
73+
finalized_at: Optional[datetime.datetime]
74+
kind: str
75+
max_attempts: int
76+
metadata: Any
77+
priority: int
78+
queue: str
79+
scheduled_at: Optional[datetime.datetime]
80+
state: models.RiverJobState
81+
tags: List[str]
82+
83+
84+
class Querier:
85+
def __init__(self, conn: sqlalchemy.engine.Connection):
86+
self._conn = conn
87+
88+
def job_get_by_kind_and_unique_properties(self, arg: JobGetByKindAndUniquePropertiesParams) -> Optional[models.RiverJob]:
89+
row = self._conn.execute(sqlalchemy.text(JOB_GET_BY_KIND_AND_UNIQUE_PROPERTIES), {
90+
"p1": arg.kind,
91+
"p2": arg.by_args,
92+
"p3": arg.args,
93+
"p4": arg.by_created_at,
94+
"p5": arg.created_at_begin,
95+
"p6": arg.created_at_end,
96+
"p7": arg.by_queue,
97+
"p8": arg.queue,
98+
"p9": arg.by_state,
99+
"p10": arg.state,
100+
}).first()
101+
if row is None:
102+
return None
103+
return models.RiverJob(
104+
id=row[0],
105+
args=row[1],
106+
attempt=row[2],
107+
attempted_at=row[3],
108+
attempted_by=row[4],
109+
created_at=row[5],
110+
errors=row[6],
111+
finalized_at=row[7],
112+
kind=row[8],
113+
max_attempts=row[9],
114+
metadata=row[10],
115+
priority=row[11],
116+
queue=row[12],
117+
state=row[13],
118+
scheduled_at=row[14],
119+
tags=row[15],
120+
)
121+
122+
def job_insert_fast(self, arg: JobInsertFastParams) -> Optional[models.RiverJob]:
123+
row = self._conn.execute(sqlalchemy.text(JOB_INSERT_FAST), {
124+
"p1": arg.args,
125+
"p2": arg.created_at,
126+
"p3": arg.finalized_at,
127+
"p4": arg.kind,
128+
"p5": arg.max_attempts,
129+
"p6": arg.metadata,
130+
"p7": arg.priority,
131+
"p8": arg.queue,
132+
"p9": arg.scheduled_at,
133+
"p10": arg.state,
134+
"p11": arg.tags,
135+
}).first()
136+
if row is None:
137+
return None
138+
return models.RiverJob(
139+
id=row[0],
140+
args=row[1],
141+
attempt=row[2],
142+
attempted_at=row[3],
143+
attempted_by=row[4],
144+
created_at=row[5],
145+
errors=row[6],
146+
finalized_at=row[7],
147+
kind=row[8],
148+
max_attempts=row[9],
149+
metadata=row[10],
150+
priority=row[11],
151+
queue=row[12],
152+
state=row[13],
153+
scheduled_at=row[14],
154+
tags=row[15],
155+
)
156+
157+
158+
class AsyncQuerier:
159+
def __init__(self, conn: sqlalchemy.ext.asyncio.AsyncConnection):
160+
self._conn = conn
161+
162+
async def job_get_by_kind_and_unique_properties(self, arg: JobGetByKindAndUniquePropertiesParams) -> Optional[models.RiverJob]:
163+
row = (await self._conn.execute(sqlalchemy.text(JOB_GET_BY_KIND_AND_UNIQUE_PROPERTIES), {
164+
"p1": arg.kind,
165+
"p2": arg.by_args,
166+
"p3": arg.args,
167+
"p4": arg.by_created_at,
168+
"p5": arg.created_at_begin,
169+
"p6": arg.created_at_end,
170+
"p7": arg.by_queue,
171+
"p8": arg.queue,
172+
"p9": arg.by_state,
173+
"p10": arg.state,
174+
})).first()
175+
if row is None:
176+
return None
177+
return models.RiverJob(
178+
id=row[0],
179+
args=row[1],
180+
attempt=row[2],
181+
attempted_at=row[3],
182+
attempted_by=row[4],
183+
created_at=row[5],
184+
errors=row[6],
185+
finalized_at=row[7],
186+
kind=row[8],
187+
max_attempts=row[9],
188+
metadata=row[10],
189+
priority=row[11],
190+
queue=row[12],
191+
state=row[13],
192+
scheduled_at=row[14],
193+
tags=row[15],
194+
)
195+
196+
async def job_insert_fast(self, arg: JobInsertFastParams) -> Optional[models.RiverJob]:
197+
row = (await self._conn.execute(sqlalchemy.text(JOB_INSERT_FAST), {
198+
"p1": arg.args,
199+
"p2": arg.created_at,
200+
"p3": arg.finalized_at,
201+
"p4": arg.kind,
202+
"p5": arg.max_attempts,
203+
"p6": arg.metadata,
204+
"p7": arg.priority,
205+
"p8": arg.queue,
206+
"p9": arg.scheduled_at,
207+
"p10": arg.state,
208+
"p11": arg.tags,
209+
})).first()
210+
if row is None:
211+
return None
212+
return models.RiverJob(
213+
id=row[0],
214+
args=row[1],
215+
attempt=row[2],
216+
attempted_at=row[3],
217+
attempted_by=row[4],
218+
created_at=row[5],
219+
errors=row[6],
220+
finalized_at=row[7],
221+
kind=row[8],
222+
max_attempts=row[9],
223+
metadata=row[10],
224+
priority=row[11],
225+
queue=row[12],
226+
state=row[13],
227+
scheduled_at=row[14],
228+
tags=row[15],
229+
)

0 commit comments

Comments
 (0)