Skip to content

Commit b80297f

Browse files
authored
Fix: Inconsistent pagination (#777)
* Fix: Inconsistent pagination - include item_hash as a tie-breaker * Fix: posts tests messages with pagination
1 parent afbe5af commit b80297f

File tree

5 files changed

+72
-31
lines changed

5 files changed

+72
-31
lines changed

src/aleph/db/accessors/files.py

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -170,12 +170,18 @@ def get_address_files_for_api(
170170
if pagination:
171171
select_stmt = select_stmt.limit(pagination).offset((page - 1) * pagination)
172172

173-
order_by = (
174-
MessageFilePinDb.created.desc()
175-
if sort_order == SortOrder.DESCENDING
176-
else MessageFilePinDb.created.asc()
177-
)
178-
select_stmt = select_stmt.order_by(order_by)
173+
if sort_order == SortOrder.DESCENDING:
174+
order_by_columns = (
175+
MessageFilePinDb.created.desc(),
176+
MessageFilePinDb.item_hash.asc(),
177+
)
178+
else: # ASCENDING
179+
order_by_columns = (
180+
MessageFilePinDb.item_hash.asc(),
181+
MessageFilePinDb.item_hash.asc(),
182+
)
183+
184+
select_stmt = select_stmt.order_by(*order_by_columns)
179185

180186
return session.execute(select_stmt).all()
181187

src/aleph/db/accessors/messages.py

Lines changed: 28 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -144,30 +144,37 @@ def make_matching_messages_query(
144144
select_stmt = select_stmt.where(
145145
select_earliest_confirmation.c.height < end_block
146146
)
147+
148+
sort_by = SortBy.TX_TIME
147149
if sort_by == SortBy.TX_TIME:
148150
order_by_columns = (
149151
(
150152
nullsfirst(
151153
select_earliest_confirmation.c.earliest_confirmation.desc()
152154
),
153155
MessageDb.time.desc(),
156+
MessageDb.item_hash.asc(),
154157
)
155158
if sort_order == SortOrder.DESCENDING
156159
else (
157160
nullslast(
158161
select_earliest_confirmation.c.earliest_confirmation.asc()
159162
),
160163
MessageDb.time.asc(),
164+
MessageDb.item_hash.asc(),
161165
)
162166
)
163167
else:
164-
order_by_columns = (
165-
(
166-
MessageDb.time.desc()
167-
if sort_order == SortOrder.DESCENDING
168-
else MessageDb.time.asc()
169-
),
170-
)
168+
if sort_order == SortOrder.DESCENDING:
169+
order_by_columns = (
170+
MessageDb.time.desc(),
171+
MessageDb.item_hash.asc(),
172+
)
173+
else: # ASCENDING
174+
order_by_columns = (
175+
MessageDb.time.asc(),
176+
MessageDb.item_hash.asc(),
177+
)
171178

172179
select_stmt = select_stmt.order_by(*order_by_columns).offset(
173180
(page - 1) * pagination
@@ -653,10 +660,20 @@ def make_matching_hashes_query(
653660
if status:
654661
select_stmt = select_stmt.where(MessageStatusDb.status == status)
655662

656-
if sort_order == SortOrder.ASCENDING:
657-
select_stmt = select_stmt.order_by(MessageStatusDb.reception_time.asc())
658-
else:
659-
select_stmt = select_stmt.order_by(MessageStatusDb.reception_time.desc())
663+
order_by_columns: Tuple = ()
664+
665+
if sort_order == SortOrder.DESCENDING:
666+
order_by_columns = (
667+
MessageStatusDb.reception_time.desc(),
668+
MessageStatusDb.item_hash.asc(),
669+
)
670+
else: # ASCENDING
671+
order_by_columns = (
672+
MessageStatusDb.reception_time.asc(),
673+
MessageStatusDb.item_hash.asc(),
674+
)
675+
676+
select_stmt = select_stmt.order_by(*order_by_columns)
660677

661678
select_stmt = select_stmt.offset((page - 1) * pagination)
662679

src/aleph/db/accessors/posts.py

Lines changed: 16 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -256,29 +256,33 @@ def filter_post_select_stmt(
256256
isouter=True,
257257
)
258258

259-
order_by_columns = (
260-
(
259+
if sort_order == SortOrder.DESCENDING:
260+
order_by_columns = (
261261
nullsfirst(
262262
select_earliest_confirmation.c.earliest_confirmation.desc()
263263
),
264264
select_merged_post_subquery.c.created.desc(),
265+
select_merged_post_subquery.c.item_hash.asc(),
265266
)
266-
if sort_order == SortOrder.DESCENDING
267-
else (
267+
else: # ASCENDING
268+
order_by_columns = (
268269
nullslast(
269270
select_earliest_confirmation.c.earliest_confirmation.asc()
270271
),
271272
select_merged_post_subquery.c.created.asc(),
273+
select_merged_post_subquery.c.item_hash.asc(),
272274
)
273-
)
274275
else:
275-
order_by_columns = (
276-
(
277-
last_updated_column.desc()
278-
if sort_order == SortOrder.DESCENDING
279-
else last_updated_column.asc()
280-
),
281-
)
276+
if sort_order == SortOrder.DESCENDING:
277+
order_by_columns = (
278+
last_updated_column.desc(),
279+
select_merged_post_subquery.c.original_item_hash.asc(),
280+
)
281+
else: # ASCENDING
282+
order_by_columns = (
283+
last_updated_column.asc(),
284+
select_merged_post_subquery.c.original_item_hash.asc(),
285+
)
282286
select_stmt = select_stmt.order_by(*order_by_columns)
283287

284288
# If pagination == 0, return all matching results

src/aleph/web/controllers/accounts.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -155,7 +155,7 @@ async def get_account_files(request: web.Request) -> web.Response:
155155
address=address,
156156
total_size=total_size,
157157
files=[
158-
GetAccountFilesResponseItem.model_validate(file_pin)
158+
GetAccountFilesResponseItem.model_validate(dict(file_pin))
159159
for file_pin in file_pins
160160
],
161161
pagination_page=query_params.page,

tests/api/test_list_messages.py

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -395,6 +395,20 @@ async def fetch_messages_with_pagination_expect_success(
395395

396396
@pytest.mark.asyncio()
397397
async def test_pagination(fixture_messages, ccn_api_client):
398+
"""
399+
forgotten_messages = list(
400+
filter(lambda msg: msg["type"] == "FORGET", fixture_messages)
401+
)
402+
forgotten_hashes = list(
403+
itertools.chain.from_iterable(
404+
[msg["content"]["hashes"] for msg in forgotten_messages]
405+
)
406+
)
407+
408+
messages_without_forgotten = list(
409+
filter(lambda msg: msg["item_hash"] not in forgotten_hashes, fixture_messages)
410+
)
411+
"""
398412
sorted_messages_by_time = sorted(fixture_messages, key=lambda msg: msg["time"])
399413

400414
# More messages than available
@@ -427,7 +441,7 @@ async def test_pagination(fixture_messages, ccn_api_client):
427441
)
428442
assert_messages_equal(messages, sorted_messages_by_time[-1:])
429443

430-
# Some messages, reverse sort order
444+
# Some messages, ascending sort order
431445
messages = await fetch_messages_with_pagination_expect_success(
432446
ccn_api_client, page=1, pagination=3, sort_order=1
433447
)

0 commit comments

Comments
 (0)