... |
... |
@@ -88,6 +88,7 @@ def changelogs_v2() -> str: |
88
|
88
|
- since: (optional) ISO date/datetime (e.g. 2024-01-01 or 2024-01-01T12:00:00)
|
89
|
89
|
- till: (optional) ISO date/datetime upper bound (inclusive)
|
90
|
90
|
- source: (optional) exact source package name to restrict
|
|
91
|
+ - since_id: (optional) return only rows with id > since_id (id-based polling)
|
91
|
92
|
- limit: (optional) default 50, max 500
|
92
|
93
|
- offset: (optional) default 0
|
93
|
94
|
|
... |
... |
@@ -100,6 +101,7 @@ def changelogs_v2() -> str: |
100
|
101
|
source_filter = bottle.request.query.get("source", "").strip()
|
101
|
102
|
since_param = bottle.request.query.get("since", "").strip()
|
102
|
103
|
till_param = bottle.request.query.get("till", "").strip()
|
|
104
|
+ since_id_str = bottle.request.query.get("since_id", "").strip()
|
103
|
105
|
|
104
|
106
|
# Pagination params
|
105
|
107
|
try:
|
... |
... |
@@ -134,6 +136,20 @@ def changelogs_v2() -> str: |
134
|
136
|
bottle.response.status = 400
|
135
|
137
|
return json.dumps({"error": "Invalid till parameter (expected ISO date)"})
|
136
|
138
|
|
|
139
|
+ # Validate id-based filter
|
|
140
|
+ since_id = None
|
|
141
|
+ if since_id_str:
|
|
142
|
+ try:
|
|
143
|
+ since_id = int(since_id_str)
|
|
144
|
+ except Exception:
|
|
145
|
+ bottle.response.status = 400
|
|
146
|
+ return json.dumps(
|
|
147
|
+ {"error": "Invalid since_id parameter (expected integer)"}
|
|
148
|
+ )
|
|
149
|
+ if since_id < 0:
|
|
150
|
+ bottle.response.status = 400
|
|
151
|
+ return json.dumps({"error": "since_id must be >= 0"})
|
|
152
|
+
|
137
|
153
|
s = DBConn().session()
|
138
|
154
|
try:
|
139
|
155
|
q = (
|
... |
... |
@@ -165,6 +181,9 @@ def changelogs_v2() -> str: |
165
|
181
|
if till_dt:
|
166
|
182
|
# Inclusive upper bound
|
167
|
183
|
q = q.filter(cast(DBChange.date, TIMESTAMP) <= till_dt)
|
|
184
|
+ if since_id is not None:
|
|
185
|
+ # Strictly greater than to avoid returning the last seen row again
|
|
186
|
+ q = q.filter(DBChange.change_id > since_id)
|
168
|
187
|
|
169
|
188
|
q = q.order_by(DBChange.seen, DBChange.change_id) # deterministic ordering
|
170
|
189
|
|