Skip to content

Commit 2416ed1

Browse files
authored
Feat/profile editor performance improvements (#942)
* fix: performance issues * fix: bullshit issues * feat: profile-editor blocking on images * fix: sync bug and cache * feat: video preview * chore: remove cache * chore: remove cache * debug: admin * feat: profile fix * fix: image * fix: image sync * chore: debug logs * fix: evault fixes * fix: public/private stuff * fix: sync delay * feat: own profile optmistic cache
1 parent 9a3a214 commit 2416ed1

23 files changed

Lines changed: 772 additions & 286 deletions

File tree

infrastructure/evault-core/src/core/db/db.service.ts

Lines changed: 36 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -565,6 +565,36 @@ export class DbService {
565565
{ id, ontology: meta.ontology, acl, eName },
566566
);
567567

568+
// Deduplicate envelopes — if multiple Envelope nodes share the
569+
// same ontology (field name), keep the first and delete the rest.
570+
// This prevents non-deterministic reads where collect(e) returns
571+
// duplicates in undefined order and reduce picks the wrong one.
572+
const seen = new Map<string, string>(); // ontology → kept envelope id
573+
const dupsToDelete: string[] = [];
574+
for (const env of existing.envelopes) {
575+
if (seen.has(env.ontology)) {
576+
dupsToDelete.push(env.id);
577+
} else {
578+
seen.set(env.ontology, env.id);
579+
}
580+
}
581+
if (dupsToDelete.length > 0) {
582+
console.warn(
583+
`[eVault] Cleaning ${dupsToDelete.length} duplicate envelope(s) for MetaEnvelope ${id}`,
584+
);
585+
for (const dupId of dupsToDelete) {
586+
await this.runQueryInternal(
587+
`MATCH (e:Envelope { id: $envelopeId }) DETACH DELETE e`,
588+
{ envelopeId: dupId },
589+
);
590+
}
591+
// Remove deleted dupes from the existing list so the update
592+
// loop below doesn't try to reference them.
593+
existing.envelopes = existing.envelopes.filter(
594+
(e) => !dupsToDelete.includes(e.id),
595+
);
596+
}
597+
568598
const createdEnvelopes: Envelope<T[keyof T]>[] = [];
569599
let counter = 0;
570600

@@ -601,21 +631,18 @@ export class DbService {
601631
valueType,
602632
});
603633
} else {
604-
// Create new envelope
634+
// Create new envelope — use MERGE on the relationship
635+
// + ontology to prevent duplicate Envelopes if two
636+
// concurrent updates race.
605637
const envW3id = await new W3IDBuilder().build();
606638
const envelopeId = envW3id.id;
607639

608640
await this.runQueryInternal(
609641
`
610642
MATCH (m:MetaEnvelope { id: $metaId, eName: $eName })
611-
CREATE (${alias}:Envelope {
612-
id: $${alias}_id,
613-
ontology: $${alias}_ontology,
614-
value: $${alias}_value,
615-
valueType: $${alias}_type
616-
})
617-
WITH m, ${alias}
618-
MERGE (m)-[:LINKS_TO]->(${alias})
643+
MERGE (m)-[:LINKS_TO]->(${alias}:Envelope { ontology: $${alias}_ontology })
644+
ON CREATE SET ${alias}.id = $${alias}_id, ${alias}.value = $${alias}_value, ${alias}.valueType = $${alias}_type
645+
ON MATCH SET ${alias}.value = $${alias}_value, ${alias}.valueType = $${alias}_type
619646
`,
620647
{
621648
metaId: id,

infrastructure/evault-core/src/core/protocol/graphql-server.ts

Lines changed: 18 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -374,12 +374,19 @@ export class GraphQLServer {
374374
context.eName,
375375
);
376376

377-
// Build the full metaEnvelope response
377+
// Build parsed from actual written envelopes, not input
378+
const parsedFromEnvelopes = result.envelopes.reduce(
379+
(acc: Record<string, any>, env: any) => {
380+
acc[env.ontology] = env.value;
381+
return acc;
382+
},
383+
{},
384+
);
378385
const metaEnvelope = {
379386
id: result.metaEnvelope.id,
380387
ontology: result.metaEnvelope.ontology,
381388
envelopes: result.envelopes,
382-
parsed: input.payload,
389+
parsed: parsedFromEnvelopes,
383390
};
384391

385392
// Deliver webhooks for create operation
@@ -508,12 +515,19 @@ export class GraphQLServer {
508515
context.eName,
509516
);
510517

511-
// Build the full metaEnvelope response
518+
// Build parsed from actual written envelopes, not input
519+
const parsedFromEnvelopes = result.envelopes.reduce(
520+
(acc: Record<string, any>, env: any) => {
521+
acc[env.ontology] = env.value;
522+
return acc;
523+
},
524+
{},
525+
);
512526
const metaEnvelope = {
513527
id: result.metaEnvelope.id,
514528
ontology: result.metaEnvelope.ontology,
515529
envelopes: result.envelopes,
516-
parsed: input.payload,
530+
parsed: parsedFromEnvelopes,
517531
};
518532

519533
// Deliver webhooks for update operation

platforms/profile-editor/api/src/controllers/DiscoveryController.ts

Lines changed: 14 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -12,26 +12,25 @@ export class DiscoveryController {
1212
try {
1313
const { q, page, limit, sortBy } = req.query;
1414

15-
if (!q) {
16-
res.setHeader("Cache-Control", "no-store, no-cache, must-revalidate");
17-
res.setHeader("Pragma", "no-cache");
18-
return res
19-
.status(400)
20-
.json({ error: 'Query parameter "q" is required' });
21-
}
22-
2315
const pageNum = Math.max(1, parseInt(page as string) || 1);
2416
const limitNum = Math.min(
2517
100,
26-
Math.max(1, parseInt(limit as string) || 10),
18+
Math.max(1, parseInt(limit as string) || 12),
2719
);
2820

29-
const results = await this.userSearchService.searchUsers(
30-
q as string,
31-
pageNum,
32-
limitNum,
33-
(sortBy as string) || "relevance",
34-
);
21+
const query = ((q as string) ?? "").trim();
22+
23+
const results = query
24+
? await this.userSearchService.searchUsers(
25+
query,
26+
pageNum,
27+
limitNum,
28+
(sortBy as string) || "relevance",
29+
)
30+
: await this.userSearchService.listPublicUsers(
31+
pageNum,
32+
limitNum,
33+
);
3534

3635
res.setHeader(
3736
"Cache-Control",

0 commit comments

Comments
 (0)