Skip to content

Commit 7fdb9e5

Browse files
committed
Fix follow pages not hydrating the profile information
1 parent 31c29ea commit 7fdb9e5

12 files changed

Lines changed: 214 additions & 173 deletions

File tree

packages/js-core/src/proto/polycentric/v2/graph_service.ts

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import { UnknownFieldHandler } from "@protobuf-ts/runtime";
1111
import type { PartialMessage } from "@protobuf-ts/runtime";
1212
import { reflectionMergePartial } from "@protobuf-ts/runtime";
1313
import { MessageType } from "@protobuf-ts/runtime";
14+
import { EventHint } from "./events";
1415
import { PageInfo } from "./common";
1516
import { EventBundle } from "./events";
1617
import { PageParams } from "./common";
@@ -58,6 +59,13 @@ export interface ListFollowsResponse {
5859
* @generated from protobuf field: optional polycentric.v2.PageInfo page_info = 2
5960
*/
6061
pageInfo?: PageInfo;
62+
/**
63+
* Identity-chain and profile events for every identity referenced by the
64+
* bundles, so clients can validate and render them without extra queries.
65+
*
66+
* @generated from protobuf field: repeated polycentric.v2.EventHint event_hints = 3
67+
*/
68+
eventHints: EventHint[];
6169
}
6270
// @generated message type with reflection information, may provide speed optimized methods
6371
class ListFollowingRequest$Type extends MessageType<ListFollowingRequest> {
@@ -172,12 +180,14 @@ class ListFollowsResponse$Type extends MessageType<ListFollowsResponse> {
172180
constructor() {
173181
super("polycentric.v2.ListFollowsResponse", [
174182
{ no: 1, name: "event_bundles", kind: "message", repeat: 2 /*RepeatType.UNPACKED*/, T: () => EventBundle },
175-
{ no: 2, name: "page_info", kind: "message", T: () => PageInfo }
183+
{ no: 2, name: "page_info", kind: "message", T: () => PageInfo },
184+
{ no: 3, name: "event_hints", kind: "message", repeat: 2 /*RepeatType.UNPACKED*/, T: () => EventHint }
176185
]);
177186
}
178187
create(value?: PartialMessage<ListFollowsResponse>): ListFollowsResponse {
179188
const message = globalThis.Object.create((this.messagePrototype!));
180189
message.eventBundles = [];
190+
message.eventHints = [];
181191
if (value !== undefined)
182192
reflectionMergePartial<ListFollowsResponse>(this, message, value);
183193
return message;
@@ -193,6 +203,9 @@ class ListFollowsResponse$Type extends MessageType<ListFollowsResponse> {
193203
case /* optional polycentric.v2.PageInfo page_info */ 2:
194204
message.pageInfo = PageInfo.internalBinaryRead(reader, reader.uint32(), options, message.pageInfo);
195205
break;
206+
case /* repeated polycentric.v2.EventHint event_hints */ 3:
207+
message.eventHints.push(EventHint.internalBinaryRead(reader, reader.uint32(), options));
208+
break;
196209
default:
197210
let u = options.readUnknownField;
198211
if (u === "throw")
@@ -211,6 +224,9 @@ class ListFollowsResponse$Type extends MessageType<ListFollowsResponse> {
211224
/* optional polycentric.v2.PageInfo page_info = 2; */
212225
if (message.pageInfo)
213226
PageInfo.internalBinaryWrite(message.pageInfo, writer.tag(2, WireType.LengthDelimited).fork(), options).join();
227+
/* repeated polycentric.v2.EventHint event_hints = 3; */
228+
for (let i = 0; i < message.eventHints.length; i++)
229+
EventHint.internalBinaryWrite(message.eventHints[i], writer.tag(3, WireType.LengthDelimited).fork(), options).join();
214230
let u = options.writeUnknownFields;
215231
if (u !== false)
216232
(u == true ? UnknownFieldHandler.onWrite : u)(this.typeName, message, writer);

packages/js-core/src/proto/polycentric/v2/verifications_service.ts

Lines changed: 9 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -31,15 +31,13 @@ export interface VerificationClaimBundle {
3131
*/
3232
claim?: EventBundle;
3333
/**
34-
* VerificationTarget events published by the claim's owner — who has
35-
* been asked to verify.
34+
* VerificationTarget events published by the claim's owner
3635
*
3736
* @generated from protobuf field: repeated polycentric.v2.EventBundle targets = 2
3837
*/
3938
targets: EventBundle[];
4039
/**
41-
* VerificationVerify events. The verifying identity is each
42-
* event's own signer.
40+
* VerificationVerify events.
4341
*
4442
* @generated from protobuf field: repeated polycentric.v2.EventBundle verifies = 3
4543
*/
@@ -63,8 +61,7 @@ export interface ListVerificationClaimsResponse {
6361
*/
6462
claimBundles: VerificationClaimBundle[];
6563
/**
66-
* Identity-chain and profile events for every identity referenced by the
67-
* bundles, so clients can validate and render them without extra queries.
64+
* Additional events that may be helpful, like relevant identity and profiles
6865
*
6966
* @generated from protobuf field: repeated polycentric.v2.EventHint event_hints = 2
7067
*/
@@ -85,14 +82,13 @@ export interface ListVerificationTargetsRequest {
8582
export interface ListVerificationTargetsResponse {
8683
/**
8784
* VerificationTarget events for the claim, published by the claim's
88-
* owner — who has been asked to verify. Deleted targets are excluded.
85+
* owner — who has been asked to verify.
8986
*
9087
* @generated from protobuf field: repeated polycentric.v2.EventBundle event_bundles = 1
9188
*/
9289
eventBundles: EventBundle[];
9390
/**
94-
* Identity-chain and profile events for every identity referenced by the
95-
* bundles, so clients can validate and render them without extra queries.
91+
* Additional events that may be helpful, like relevant identity and profiles
9692
*
9793
* @generated from protobuf field: repeated polycentric.v2.EventHint event_hints = 2
9894
*/
@@ -112,15 +108,13 @@ export interface ListVerificationVerifiesRequest {
112108
*/
113109
export interface ListVerificationVerifiesResponse {
114110
/**
115-
* VerificationVerify events for the claim, excluding deleted ones.
116-
* The verifying identity is each event's own signer.
111+
* VerificationVerify events for the claim.
117112
*
118113
* @generated from protobuf field: repeated polycentric.v2.EventBundle event_bundles = 1
119114
*/
120115
eventBundles: EventBundle[];
121116
/**
122-
* Identity-chain and profile events for every identity referenced by the
123-
* bundles, so clients can validate and render them without extra queries.
117+
* Additional events that may be helpful, like relevant identity and profiles
124118
*
125119
* @generated from protobuf field: repeated polycentric.v2.EventHint event_hints = 2
126120
*/
@@ -140,15 +134,13 @@ export interface ListTargetedVerificationClaimsRequest {
140134
*/
141135
export interface ListTargetedVerificationClaimsResponse {
142136
/**
143-
* Claims whose owner targeted `target_identity` — the identity's inbox
144-
* of verification requests.
137+
* Claims whose owner targeted `target_identity`. The 'inbox'.
145138
*
146139
* @generated from protobuf field: repeated polycentric.v2.VerificationClaimBundle claim_bundles = 1
147140
*/
148141
claimBundles: VerificationClaimBundle[];
149142
/**
150-
* Identity-chain and profile events for every identity referenced by the
151-
* bundles, so clients can validate and render them without extra queries.
143+
* Additional events that may be helpful, like relevant identity and profiles
152144
*
153145
* @generated from protobuf field: repeated polycentric.v2.EventHint event_hints = 2
154146
*/

packages/rs-core/src/query/graph.rs

Lines changed: 32 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ use prost::Message;
1414
use crate::client::PolycentricClient;
1515
use crate::query::event::dedup::{EventDedupKey, event_dedup_key};
1616
use crate::query::feed::{FakeCursorToken, merge_page_info};
17-
use crate::query::validation::retain_validated_bundles;
17+
use crate::query::validation::{retain_validated_bundles, retain_validated_hints};
1818
use crate::query::{QueryClient, QueryKey, QueryObservable, QueryOpts, channel};
1919

2020
#[derive(Clone, Debug, uniffi::Record)]
@@ -68,6 +68,7 @@ fn merge_follows_responses(values: &[Vec<u8>], client: &Arc<Mutex<PolycentricCli
6868
for v in values {
6969
if let Ok(incoming) = ListFollowsResponse::decode(v.as_slice()) {
7070
merged.event_bundles.extend(incoming.event_bundles);
71+
merged.event_hints.extend(incoming.event_hints);
7172
merged.page_info = merge_page_info(merged.page_info, incoming.page_info);
7273
}
7374
}
@@ -91,8 +92,17 @@ fn merge_follows_responses(values: &[Vec<u8>], client: &Arc<Mutex<PolycentricCli
9192
Reverse(created_at)
9293
});
9394

95+
let mut seen_hints: HashSet<EventDedupKey> = HashSet::new();
96+
merged.event_hints.retain(
97+
|hint| match hint.event_bundle.as_ref().and_then(event_dedup_key) {
98+
Some(k) => seen_hints.insert(k),
99+
None => true,
100+
},
101+
);
102+
94103
let c = client.lock().unwrap();
95104
retain_validated_bundles(&c, &mut merged.event_bundles);
105+
retain_validated_hints(&c, &mut merged.event_hints);
96106
drop(c);
97107

98108
merged.encode_to_vec()
@@ -139,7 +149,16 @@ pub fn list_following(
139149
prepare_page_info(&mut response, &server_url, backward_offset, forward_offset)?;
140150
let bytes = response.encode_to_vec();
141151

142-
client.lock().unwrap().copy_bundles(response.event_bundles);
152+
let hint_bundles: Vec<_> = response
153+
.event_hints
154+
.into_iter()
155+
.filter_map(|h| h.event_bundle)
156+
.collect();
157+
{
158+
let mut c = client.lock().unwrap();
159+
c.copy_bundles(hint_bundles);
160+
c.copy_bundles(response.event_bundles);
161+
}
143162
Ok(bytes)
144163
}
145164
};
@@ -188,7 +207,16 @@ pub fn list_followers(
188207
prepare_page_info(&mut response, &server_url, backward_offset, forward_offset)?;
189208
let bytes = response.encode_to_vec();
190209

191-
client.lock().unwrap().copy_bundles(response.event_bundles);
210+
let hint_bundles: Vec<_> = response
211+
.event_hints
212+
.into_iter()
213+
.filter_map(|h| h.event_bundle)
214+
.collect();
215+
{
216+
let mut c = client.lock().unwrap();
217+
c.copy_bundles(hint_bundles);
218+
c.copy_bundles(response.event_bundles);
219+
}
192220
Ok(bytes)
193221
}
194222
};
@@ -208,6 +236,7 @@ mod tests {
208236
fn response_from(server: &str, has_next_page: bool) -> Vec<u8> {
209237
let mut response = ListFollowsResponse {
210238
event_bundles: Vec::new(),
239+
event_hints: Vec::new(),
211240
page_info: Some(PageInfo {
212241
start_cursor: "start".to_string(),
213242
end_cursor: "end".to_string(),

protos/polycentric/v2/graph_service.proto

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,8 @@ message ListFollowsResponse {
2020
// The active (non-tombstoned) Follow events, newest first.
2121
repeated EventBundle event_bundles = 1;
2222
optional PageInfo page_info = 2;
23+
// Relevant events for the users in the follow events
24+
repeated EventHint event_hints = 3;
2325
}
2426

2527
service GraphService {

services/server/src/data/hydration.rs

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
use std::collections::HashMap;
22

3-
use polycentric_common::models::protos_v2::EventBundle;
3+
use polycentric_common::models::protos_v2::{EventBundle, EventHint};
44

55
use crate::service::events::TargetEventKey;
66
use crate::service::events::tombstone::EventWithContentRow;
@@ -13,3 +13,17 @@ pub struct HydrationState {
1313
pub quote_post_events: Vec<EventWithContentRow>,
1414
pub repost_events: Vec<EventWithContentRow>,
1515
}
16+
17+
impl HydrationState {
18+
/// The hydrated identity-chain and profile rows as `EventHint`s, so
19+
/// clients can validate and render the referenced identities without
20+
/// extra queries.
21+
pub fn identity_profile_hints(self) -> Vec<EventHint> {
22+
crate::service::identity::service::rows_to_hints(
23+
self.identity_events
24+
.into_iter()
25+
.chain(self.profile_events)
26+
.collect(),
27+
)
28+
}
29+
}

services/server/src/service/events/rpc/list_events.rs

Lines changed: 8 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ use crate::service::events::repository::Query as EventsRepository;
99
use crate::service::events::tombstone::EventWithContentRow;
1010
use crate::service::identity::service::{
1111
collect_identities, list_identity_events, list_profile_events,
12-
rows_to_bundles,
12+
rows_to_bundles, rows_to_hints,
1313
};
1414
use crate::service::proofs::service::attach_proofs;
1515
use crate::service::proto::{
@@ -92,7 +92,10 @@ async fn hydrate(
9292
_params: &Params,
9393
rows: &Vec<EventWithContentRow>,
9494
) -> Result<HydrationState, Status> {
95-
let identities = collect_identities(rows);
95+
let identities = collect_identities(
96+
rows.iter()
97+
.map(|(event, content)| (event, content.as_ref())),
98+
);
9699
let (identity_events, profile_events) = tokio::try_join!(
97100
list_identity_events(ctx, identities.clone()),
98101
list_profile_events(ctx, identities),
@@ -129,17 +132,9 @@ async fn view(
129132
let mut event_bundles = rows_to_bundles(live_rows);
130133
attach_proofs(ctx, &mut event_bundles).await?;
131134

132-
let mut event_hints: Vec<EventHint> = Vec::new();
133-
event_hints.extend(rows_to_bundles(identity_events).into_iter().map(|b| {
134-
EventHint {
135-
event_bundle: Some(b),
136-
}
137-
}));
138-
event_hints.extend(rows_to_bundles(profile_events).into_iter().map(|b| {
139-
EventHint {
140-
event_bundle: Some(b),
141-
}
142-
}));
135+
let event_hints = rows_to_hints(
136+
identity_events.into_iter().chain(profile_events).collect(),
137+
);
143138

144139
Ok(View {
145140
event_bundles,

services/server/src/service/feeds/rpc/common.rs

Lines changed: 8 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,8 @@ use crate::service::feeds::util::{
1414
PageCursor, PageInfo, map_db_err, page_limit,
1515
};
1616
use crate::service::identity::service::{
17-
collect_identities, list_identity_events, list_profile_events,
18-
rows_to_bundles,
17+
bundles_to_hints, collect_identities, list_identity_events,
18+
list_profile_events, rows_to_bundles, rows_to_hints,
1919
};
2020

2121
use crate::service::proofs::service::attach_proofs;
@@ -184,7 +184,10 @@ pub async fn hydrate(
184184

185185
let keys: Vec<TargetEventKey> =
186186
rows.iter().map(|(e, _)| TargetEventKey::of(e)).collect();
187-
let identities = collect_identities(rows);
187+
let identities = collect_identities(
188+
rows.iter()
189+
.map(|(event, content)| (event, content.as_ref())),
190+
);
188191
let (quote_keys, repost_keys) = collect_referenced_keys(rows);
189192

190193
// Returns valid (as far as the server is concerned) tombstones related to queried events
@@ -345,15 +348,8 @@ pub async fn view(
345348
.chain(quote_post_events)
346349
.chain(repost_events)
347350
.collect();
348-
let mut event_hints: Vec<EventHint> = rows_to_bundles(hint_rows)
349-
.into_iter()
350-
.map(|b| EventHint {
351-
event_bundle: Some(b),
352-
})
353-
.collect();
354-
event_hints.extend(tombstone_bundles.into_iter().map(|b| EventHint {
355-
event_bundle: Some(b),
356-
}));
351+
let mut event_hints = rows_to_hints(hint_rows);
352+
event_hints.extend(bundles_to_hints(tombstone_bundles));
357353

358354
Ok(GetFeedResponseView {
359355
event_bundles,

0 commit comments

Comments
 (0)