Skip to content

Commit 570a302

Browse files
authored
Merge pull request #1638 from tunjid/tj/starter-pack-follow-data-2
Starter pack follow data layer 2
2 parents f482dce + 78194b7 commit 570a302

6 files changed

Lines changed: 69 additions & 64 deletions

File tree

data/core/src/commonMain/kotlin/com/tunjid/heron/data/repository/ProfileRepository.kt

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -851,7 +851,6 @@ internal class OfflineProfileRepository(
851851
uri = connection.starterPackUri.uri.let(::AtUri),
852852
)
853853

854-
// Enumerate all of the pack list's members in memory; nothing is persisted.
855854
val members = buildList {
856855
var cursor: String? = null
857856
for (page in 0 until MaxStarterPackMemberPages) {
@@ -971,19 +970,13 @@ private fun ProfileTab.asNetworkTab(): PutTabsRequestItemUnion = when (this) {
971970
)
972971
}
973972

974-
/**
975-
* A single pending starter-pack follow: the [ApplyWritesCreate] to send plus the data needed to
976-
* reflect the follow locally once its batch commits.
977-
*/
978973
private class StarterPackFollowWrite(
979974
val memberId: ProfileId,
980975
val followedBy: FollowUri?,
981976
val followUri: FollowUri,
982977
val create: ApplyWritesCreate,
983978
)
984979

985-
// Starter-pack lists are capped well below these bounds; they simply keep a single "follow all"
986-
// from fanning out unbounded work.
987980
private const val MaxStarterPackMemberPages = 6
988981
private const val StarterPackMemberPageLimit = 50L
989982
private const val MaxFollowWritesPerBatch = 50

data/core/src/commonMain/kotlin/com/tunjid/heron/data/repository/records/BlueskyRecordOperations.kt

Lines changed: 56 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -405,6 +405,7 @@ internal class OfflineFirstBlueskyRecordOperations(
405405
add(list)
406406
items.forEach { listItemView ->
407407
add(
408+
viewingProfileId = signedInProfileId,
408409
listUri = list.uri.atUri.let(::ListUri),
409410
listItemView = listItemView,
410411
)
@@ -527,52 +528,57 @@ internal class OfflineFirstBlueskyRecordOperations(
527528
cursor: Cursor,
528529
): Flow<CursorList<StarterPack>> =
529530
if (query.query.isBlank()) emptyFlow()
530-
else networkService.observedItems(
531-
cursor = cursor,
532-
responseFetcher = {
533-
searchStarterPacksV2(
534-
params = SearchStarterPacksV2QueryParams(
535-
q = query.query,
536-
limit = query.data.limit,
537-
cursor = cursor.value,
538-
),
539-
)
540-
},
541-
responseSaver = { response ->
542-
multipleEntitySaverProvider.saveInTransaction {
543-
response.starterPacks
544-
.forEach { starterPackView ->
545-
add(starterPack = starterPackView)
546-
}
547-
}
548-
},
549-
responseCursor = { response ->
550-
response.cursor?.let(Cursor::Next)
551-
},
552-
networkItems = { _, _ ->
553-
null
554-
},
555-
observedItems = { response, nextCursor ->
556-
val starterPackUris = response.starterPacks
557-
.map { it.uri.atUri.let(::StarterPackUri) }
558-
559-
starterPackDao.starterPacks(
560-
uris = starterPackUris,
561-
)
562-
.distinctUntilChangedMap { populatedStarterPackEntities ->
563-
CursorList(
564-
items = populatedStarterPackEntities
565-
.map(PopulatedStarterPackEntity::asExternalModel)
566-
.sortedWithNetworkList(
567-
networkList = starterPackUris,
568-
databaseId = { it.uri.uri },
569-
networkId = { it.uri },
570-
),
571-
nextCursor = nextCursor,
572-
)
531+
else savedStateDataSource.singleSessionFlow { signedInProfileId ->
532+
networkService.observedItems(
533+
cursor = cursor,
534+
responseFetcher = {
535+
searchStarterPacksV2(
536+
params = SearchStarterPacksV2QueryParams(
537+
q = query.query,
538+
limit = query.data.limit,
539+
cursor = cursor.value,
540+
),
541+
)
542+
},
543+
responseSaver = { response ->
544+
multipleEntitySaverProvider.saveInTransaction {
545+
response.starterPacks
546+
.forEach { starterPackView ->
547+
add(
548+
viewingProfileId = signedInProfileId,
549+
starterPack = starterPackView,
550+
)
551+
}
573552
}
574-
},
575-
)
553+
},
554+
responseCursor = { response ->
555+
response.cursor?.let(Cursor::Next)
556+
},
557+
networkItems = { _, _ ->
558+
null
559+
},
560+
observedItems = { response, nextCursor ->
561+
val starterPackUris = response.starterPacks
562+
.map { it.uri.atUri.let(::StarterPackUri) }
563+
564+
starterPackDao.starterPacks(
565+
uris = starterPackUris,
566+
)
567+
.distinctUntilChangedMap { populatedStarterPackEntities ->
568+
CursorList(
569+
items = populatedStarterPackEntities
570+
.map(PopulatedStarterPackEntity::asExternalModel)
571+
.sortedWithNetworkList(
572+
networkList = starterPackUris,
573+
databaseId = { it.uri.uri },
574+
networkId = { it.uri },
575+
),
576+
nextCursor = nextCursor,
577+
)
578+
}
579+
},
580+
)
581+
}
576582
.flowOn(ioDispatcher)
577583

578584
override fun suggestedFeeds(): Flow<List<FeedGenerator>> =
@@ -611,7 +617,7 @@ internal class OfflineFirstBlueskyRecordOperations(
611617
.flowOn(ioDispatcher)
612618

613619
override fun suggestedStarterPacks(): Flow<List<StarterPack>> =
614-
savedStateDataSource.singleAuthorizedSessionFlow {
620+
savedStateDataSource.singleAuthorizedSessionFlow { signedInProfileId ->
615621
val starterPackViews = networkService.runCatchingWithMonitoredNetworkRetry {
616622
getSuggestedStarterPacksUnspecced(
617623
GetSuggestedStarterPacksQueryParams(),
@@ -623,7 +629,10 @@ internal class OfflineFirstBlueskyRecordOperations(
623629

624630
multipleEntitySaverProvider.saveInTransaction {
625631
starterPackViews.forEach { starterPack ->
626-
add(starterPack = starterPack)
632+
add(
633+
viewingProfileId = signedInProfileId,
634+
starterPack = starterPack,
635+
)
627636
}
628637
}
629638

data/core/src/commonMain/kotlin/com/tunjid/heron/data/utilities/multipleEntitysaver/SaveListItemView.kt

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,15 +21,18 @@ import com.tunjid.heron.data.core.types.ListMemberUri
2121
import com.tunjid.heron.data.core.types.ListUri
2222
import com.tunjid.heron.data.core.types.ProfileId
2323
import com.tunjid.heron.data.database.entities.ListMemberEntity
24-
import com.tunjid.heron.data.network.models.profileEntity
2524
import com.tunjid.heron.data.utilities.tidInstant
2625

2726
internal fun MultipleEntitySaver.add(
27+
viewingProfileId: ProfileId?,
2828
listUri: ListUri,
2929
listItemView: ListItemView,
3030
) {
3131
val createdAt = listItemView.uri.tidInstant ?: return
32-
add(listItemView.subject.profileEntity())
32+
add(
33+
viewingProfileId = viewingProfileId,
34+
profileView = listItemView.subject,
35+
)
3336
add(
3437
ListMemberEntity(
3538
listUri = listUri,

data/core/src/commonMain/kotlin/com/tunjid/heron/data/utilities/multipleEntitysaver/SaveStarterPackView.kt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ import com.tunjid.heron.data.database.entities.StarterPackEntity
2727
import com.tunjid.heron.data.network.models.profileEntity
2828

2929
internal fun MultipleEntitySaver.add(
30+
viewingProfileId: ProfileId?,
3031
starterPack: StarterPackView,
3132
) {
3233
val bskyStarterPack = try {
@@ -44,6 +45,7 @@ internal fun MultipleEntitySaver.add(
4445
)
4546
starterPack.listItemsSample?.forEach { listItemView ->
4647
add(
48+
viewingProfileId = viewingProfileId,
4749
listUri = listView.uri.atUri.let(::ListUri),
4850
listItemView = listItemView,
4951
)

data/core/src/commonMain/kotlin/com/tunjid/heron/data/utilities/recordResolver/RecordResolver.kt

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -466,7 +466,12 @@ internal class OfflineRecordResolver(
466466
)
467467
}
468468
.mapCatchingUnlessCancelled {
469-
multipleEntitySaverProvider.saveInTransaction { add(it.starterPack) }
469+
multipleEntitySaverProvider.saveInTransaction {
470+
add(
471+
viewingProfileId = viewingProfileId,
472+
starterPack = it.starterPack,
473+
)
474+
}
470475
it.starterPack.asExternalModel()
471476
}
472477
is LabelerUri -> networkService.runCatchingWithMonitoredNetworkRetry(times = 2) {

data/models/src/commonMain/kotlin/com/tunjid/heron/data/core/models/Profile.kt

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -73,12 +73,6 @@ data class Profile(
7373
val followUri: FollowUri,
7474
) : Connection()
7575

76-
/**
77-
* Bulk-follows every not-yet-followed member of a starter pack in a single batched
78-
* write. Members are derived from [listUri] (the pack's list); [starterPackUri] and
79-
* [starterPackCid] form the `via` strong-ref stamped on each follow record so the pack
80-
* creator gets join attribution.
81-
*/
8276
@Serializable
8377
data class FollowStarterPack(
8478
override val signedInProfileId: ProfileId,
@@ -163,7 +157,6 @@ data class Profile(
163157
val verifiedStatus: Status,
164158
val trustedVerifierStatus: Status,
165159
) {
166-
val isVerified get() = verifiedStatus == Status.Valid
167160
val isTrustedVerifier get() = trustedVerifierStatus == Status.Valid
168161

169162
@Serializable

0 commit comments

Comments
 (0)