When a user is following several accounts, they may get a stale feed
caused by the subscription request being rejected by relays (due to max filter item limits).
This commit implements a fix that gets around the issue by
creating several chunked filters for the home feed event and contact
metadata subscriptions.
This is a short to medium-term practical fix, where we get around the
practical limitations imposed by most relays. In the future we should
work on longer-term solutions, which will likely require protocol improvements
Main Test
---------
Procedure:
1. Login with Elsat's npub (Or some account that follows about 2K people)
2. Check the home feed. There should be fresh notes.
REPRO:
Device: iPhone 15 simulator
iOS: 17.4
Damus: 1.9 (3) (0d9954290a)
Results:
- No fresh notes, most recent post is from several hours ago (Feed is stale)
FIX TEST:
Device: iPhone 15 simulator
iOS: 17.4
Damus: This commit
Results:
- Fresh notes appear, most recent post is from a few seconds ago.
Other testing:
--------------
- New automated test passing
- All other automated tests passing
- Tested scrolling down the feed on these conditions:
- Device: iPhone 13 Mini
- iOS: 17.4.1
- Accounts:
- One with about 160 contacts and 10 relays (Daniel D’Aquino)
- One with about 1K+ contacts and 9 relays (Freedom Smuggler)
- One with about 981 contacts and 6 relays (jb55)
- Elsat's account (2K+ accounts and 8 relays)
- Result: None of those were stale
Changelog-Fixed: Fix stale feed issue when follow list is too big
Closes: https://github.com/damus-io/damus/issues/2194
Signed-off-by: Daniel D’Aquino <daniel@daquino.me>
Reviewed-by: William Casarin <jb55@jb55.com>
78 lines
4.8 KiB
Swift
78 lines
4.8 KiB
Swift
//
|
||
// NostrFilterTests.swift
|
||
// damusTests
|
||
//
|
||
// Created by Daniel D’Aquino on 2024-05-10.
|
||
//
|
||
|
||
import XCTest
|
||
@testable import damus
|
||
|
||
final class NostrFilterTests: XCTestCase {
|
||
func testChunkedWithPubKeys() {
|
||
// Given a NostrFilter with a list of pubkeys
|
||
let test_pubkey_1 = Pubkey(hex: "760f108754eb415561239d4079e71766d87e23f7e71c8e5b00d759e54dd8d082")!
|
||
let test_pubkey_2 = Pubkey(hex: "065eab63e939ea2f2f72f2305886b13e5e301302da67b5fe8a18022b278fe872")!
|
||
let test_pubkey_3 = Pubkey(hex: "aa146d7c6618ebe993702a74c561f54fc046c8a16e388b828cb2f631a1ed9602")!
|
||
let test_pubkey_4 = Pubkey(hex: "2f7108dcd33fb484be3e09cea24a1e96868fbc0842e691ca19db63781801089e")!
|
||
let test_pubkey_5 = Pubkey(hex: "1cc7c458e6b565a856d7c3791f4eb5ca5890b1f2433f452ed7a917f9aa0e5250")!
|
||
let test_pubkey_6 = Pubkey(hex: "2ee1f46a847b6613c33fd766db1e64c7f727c63774fa3ee952261d2c03b81cf2")!
|
||
let test_pubkey_7 = Pubkey(hex: "214664a7ca3236b9dd5f76550d322f390fd70cc12908a2e3ff2cdf50085d4ef2")!
|
||
let test_pubkey_8 = Pubkey(hex: "40255b02f3d8ccd6178d50f5ce1c1ac2867b3d919832176957b021c1816fce2f")!
|
||
let pubkeys: [Pubkey] = [test_pubkey_1, test_pubkey_2, test_pubkey_3, test_pubkey_4]
|
||
let authors: [Pubkey] = [test_pubkey_5, test_pubkey_6, test_pubkey_7, test_pubkey_8]
|
||
let filter = NostrFilter(
|
||
pubkeys: pubkeys,
|
||
authors: authors
|
||
)
|
||
|
||
let chunked_pubkeys_filters_size_2 = filter.chunked(on: .pubkeys, into: 2)
|
||
XCTAssertEqual(chunked_pubkeys_filters_size_2.count, 2)
|
||
XCTAssertEqual(chunked_pubkeys_filters_size_2[0].pubkeys, [test_pubkey_1, test_pubkey_2])
|
||
XCTAssertEqual(chunked_pubkeys_filters_size_2[1].pubkeys, [test_pubkey_3, test_pubkey_4])
|
||
XCTAssertEqual(chunked_pubkeys_filters_size_2[0].authors, authors)
|
||
XCTAssertEqual(chunked_pubkeys_filters_size_2[1].authors, authors)
|
||
|
||
let chunked_pubkeys_filters_size_3 = filter.chunked(on: .pubkeys, into: 3)
|
||
XCTAssertEqual(chunked_pubkeys_filters_size_3.count, 2)
|
||
XCTAssertEqual(chunked_pubkeys_filters_size_3[0].pubkeys, [test_pubkey_1, test_pubkey_2, test_pubkey_3])
|
||
XCTAssertEqual(chunked_pubkeys_filters_size_3[1].pubkeys, [test_pubkey_4])
|
||
XCTAssertEqual(chunked_pubkeys_filters_size_3[0].authors, authors)
|
||
XCTAssertEqual(chunked_pubkeys_filters_size_3[1].authors, authors)
|
||
|
||
let chunked_pubkeys_filters_size_4 = filter.chunked(on: .pubkeys, into: 4)
|
||
XCTAssertEqual(chunked_pubkeys_filters_size_4.count, 1)
|
||
XCTAssertEqual(chunked_pubkeys_filters_size_4[0].pubkeys, [test_pubkey_1, test_pubkey_2, test_pubkey_3, test_pubkey_4])
|
||
XCTAssertEqual(chunked_pubkeys_filters_size_4[0].authors, authors)
|
||
|
||
let chunked_pubkeys_filters_size_5 = filter.chunked(on: .pubkeys, into: 5)
|
||
XCTAssertEqual(chunked_pubkeys_filters_size_5.count, 1)
|
||
XCTAssertEqual(chunked_pubkeys_filters_size_5[0].pubkeys, [test_pubkey_1, test_pubkey_2, test_pubkey_3, test_pubkey_4])
|
||
XCTAssertEqual(chunked_pubkeys_filters_size_5[0].authors, authors)
|
||
|
||
let chunked_authors_filters_size_2 = filter.chunked(on: .authors, into: 2)
|
||
XCTAssertEqual(chunked_authors_filters_size_2.count, 2)
|
||
XCTAssertEqual(chunked_authors_filters_size_2[0].authors, [test_pubkey_5, test_pubkey_6])
|
||
XCTAssertEqual(chunked_authors_filters_size_2[1].authors, [test_pubkey_7, test_pubkey_8])
|
||
XCTAssertEqual(chunked_authors_filters_size_2[0].pubkeys, pubkeys)
|
||
XCTAssertEqual(chunked_authors_filters_size_2[1].pubkeys, pubkeys)
|
||
|
||
let chunked_authors_filters_size_3 = filter.chunked(on: .authors, into: 3)
|
||
XCTAssertEqual(chunked_authors_filters_size_3.count, 2)
|
||
XCTAssertEqual(chunked_authors_filters_size_3[0].authors, [test_pubkey_5, test_pubkey_6, test_pubkey_7])
|
||
XCTAssertEqual(chunked_authors_filters_size_3[1].authors, [test_pubkey_8])
|
||
XCTAssertEqual(chunked_authors_filters_size_3[0].pubkeys, pubkeys)
|
||
XCTAssertEqual(chunked_authors_filters_size_3[1].pubkeys, pubkeys)
|
||
|
||
let chunked_authors_filters_size_4 = filter.chunked(on: .authors, into: 4)
|
||
XCTAssertEqual(chunked_authors_filters_size_4.count, 1)
|
||
XCTAssertEqual(chunked_authors_filters_size_4[0].authors, [test_pubkey_5, test_pubkey_6, test_pubkey_7, test_pubkey_8])
|
||
XCTAssertEqual(chunked_authors_filters_size_4[0].pubkeys, pubkeys)
|
||
|
||
let chunked_authors_filters_size_5 = filter.chunked(on: .authors, into: 5)
|
||
XCTAssertEqual(chunked_authors_filters_size_5.count, 1)
|
||
XCTAssertEqual(chunked_authors_filters_size_5[0].authors, [test_pubkey_5, test_pubkey_6, test_pubkey_7, test_pubkey_8])
|
||
XCTAssertEqual(chunked_authors_filters_size_5[0].pubkeys, pubkeys)
|
||
}
|
||
}
|