Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[CORL-3172] optimized redis query for counts v2 endpoint #4660

Merged
Merged
Changes from all commits
Commits
Show all changes
101 commits
Select commit Hold shift + click to select a range
85b71b0
create preliminary tenor search handler
nick-funk May 24, 2024
9b5d878
Merge pull request #4623 from coralproject/develop
tessalt Jun 3, 2024
4e49751
add German translations for notifications
bastiankistner Jun 5, 2024
404df46
improve German translation
bastiankistner Jun 5, 2024
9ef8979
Merge branch 'develop' into feat/CORL-3171-tenor
nick-funk Jun 11, 2024
e49007f
fix typo
lusbuab Jun 17, 2024
17caa8d
update schema to use `gifs` with `provider` instead of `giphy`
nick-funk Jun 21, 2024
2e6a28f
update Configure > General to support both tenor and giphy modes
nick-funk Jun 21, 2024
941fad5
add `TenorMedia` to schema and resolvers
nick-funk Jun 21, 2024
4c678fd
create preliminary Tenor search input
nick-funk Jun 21, 2024
1fd8be9
allow tenor gifs to show in stream
nick-funk Jun 21, 2024
41dc8e2
remove un-necessary context dependency from GifFetch
nick-funk Jun 21, 2024
97ddf5c
rename `giphy` to `gifs` in `.../client/admin/test/fixtures`
nick-funk Jun 24, 2024
796abbf
add `TenorMedia` to admin
nick-funk Jun 24, 2024
336c611
update some more fixtures to be happy with `giphy` -> `gifs` rename
nick-funk Jun 24, 2024
86d68ac
add title to `TenorMedia` schema type
nick-funk Jun 24, 2024
c05a6a8
replace tenor attribution gif with a png so linting stops whining
nick-funk Jun 28, 2024
c746b08
grab the ORIGIN from the count.js script src
kabeaty Jun 28, 2024
249cc61
fix powered by tenor alt text translation
nick-funk Jun 28, 2024
d0cc5e0
Merge pull request #4638 from coralproject/bug/CORL-3177-count-script…
tessalt Jul 2, 2024
ce2e09b
update package to 9.0.8
tessalt Jul 2, 2024
2e13a7e
Merge pull request #4639 from coralproject/release-9.0.8
tessalt Jul 2, 2024
63a2985
Merge branch 'main' into develop
tessalt Jul 2, 2024
575d4ee
Merge pull request #4640 from coralproject/develop
tessalt Jul 2, 2024
fb8c2f3
convert giphy content filter ratings to tenor filter levels
nick-funk Jul 2, 2024
a51fa2b
rename `giphy` to `gifs` in enabled helper func
nick-funk Jul 4, 2024
69c6ccc
update validators for comment posting around tenor/giphy
nick-funk Jul 4, 2024
771006c
allow tenor through minimum content length checks
nick-funk Jul 4, 2024
9045f52
clean up styles of tenor gif search results
nick-funk Jul 4, 2024
176d775
provide a few more tenor search results per query
nick-funk Jul 4, 2024
16a3043
slightly increase size of tenor search result images
nick-funk Jul 4, 2024
9444e0a
update repeat post to check for `tenor`
nick-funk Jul 4, 2024
9413256
Merge branch 'develop' into feat/CORL-3171-tenor
nick-funk Jul 4, 2024
6961cf9
run external mod phases before pre-moderation steps
nick-funk Jul 4, 2024
372ef4d
add a `api/none` endpoint to `utilities/externalModPhase`
nick-funk Jul 4, 2024
58e04a3
rename GiphyMedia to TenorMedia
nick-funk Jul 9, 2024
3376719
set tenor media styles with css
nick-funk Jul 9, 2024
b29a766
use previews for search results grid
nick-funk Jul 9, 2024
b018ee6
use gif title for alt text if possible
nick-funk Jul 9, 2024
351c072
remove commented out flex styles for gifs
nick-funk Jul 9, 2024
8150155
fix old GiphyAttribution imports used in TenorInput
nick-funk Jul 9, 2024
9748d64
rename comment on gif's field in schema
nick-funk Jul 9, 2024
4a96f8d
consolidate the gif search input into a shared component
nick-funk Jul 9, 2024
2fdf4a9
remove old tenant not found error comment
nick-funk Jul 9, 2024
7506d63
extract tenor search url into constant
nick-funk Jul 9, 2024
91e5251
update embed links description to generalize "gifs"
nick-funk Jul 9, 2024
22bc850
update enableGifs text for all languages
nick-funk Jul 9, 2024
f09d2a6
update `show/hide giphy` to `show/hide gif` in translations
nick-funk Jul 9, 2024
4641df9
handle tenor media in single comment embed
nick-funk Jul 9, 2024
b4e90d4
Merge pull request #4633 from coralproject/feat/CORL-3171-tenor
tessalt Jul 11, 2024
e33f1b7
update version to 9.1.0
tessalt Jul 11, 2024
583ec80
Merge pull request #4643 from coralproject/release-9.1.0
tessalt Jul 11, 2024
d66eb4b
use new tenor string based content filters
nick-funk Jul 11, 2024
bf2e463
Merge branch 'develop' into feat/CORL-3171-tenor
nick-funk Jul 11, 2024
8226af4
Merge pull request #4645 from coralproject/feat/CORL-3171-tenor
tessalt Jul 11, 2024
169fa60
Merge branch 'main' into develop
tessalt Jul 11, 2024
3c1257f
add pagination to tenor gif search
nick-funk Jul 12, 2024
fdedeae
Merge branch 'develop' into feat/CORL-3171-tenor-pagination
nick-funk Jul 12, 2024
2b70dcc
make linter happy about fetch types
nick-funk Jul 12, 2024
6a23540
don't show load more if no search results
nick-funk Jul 12, 2024
44169d9
Merge pull request #4646 from coralproject/feat/CORL-3171-tenor-pagin…
tessalt Jul 15, 2024
e1bb865
use the framework url utilities to process url's
nick-funk Jul 15, 2024
8377118
set the tenor debounce delay to 1250 ms
nick-funk Jul 15, 2024
4ec66d0
Merge branch 'develop' into fix/CORL-3171-tenor-url-protocol
tessalt Jul 15, 2024
7f7baff
Merge remote-tracking branch 'origin/fix/CORL-3171-tenor-url-protocol…
nick-funk Jul 15, 2024
b403ab0
Merge branch 'main' into patch-1
tessalt Jul 15, 2024
5f926f7
Merge branch 'develop' into develop
tessalt Jul 15, 2024
d766e3d
pass the next param into the `loadMoreGifs` fetch call
nick-funk Jul 15, 2024
37036c4
don't show load more if query is empty
nick-funk Jul 15, 2024
339220f
Merge pull request #4634 from lusbuab/patch-1
tessalt Jul 15, 2024
8b6f823
Merge pull request #4629 from bastiankistner/develop
tessalt Jul 15, 2024
466fe54
Merge pull request #4647 from coralproject/fix/CORL-3171-tenor-url-pr…
tessalt Jul 16, 2024
ae68093
Merge branch 'main' into develop
tessalt Jul 16, 2024
a66c2bf
Merge pull request #4644 from coralproject/develop
tessalt Jul 17, 2024
5cfdfd2
update version to 9.1.1
tessalt Jul 17, 2024
6832754
Merge branch 'main' into develop
tessalt Jul 17, 2024
c85d27b
Merge pull request #4648 from coralproject/develop
tessalt Jul 17, 2024
8e596ec
add max width to tenor image
tessalt Jul 17, 2024
e872270
Merge branch 'develop' into fix/tenor-image-width
tessalt Jul 17, 2024
fa337fd
Merge pull request #4649 from coralproject/fix/tenor-image-width
tessalt Jul 18, 2024
6a6b4f6
bump version
tessalt Jul 18, 2024
2e01fe2
Merge pull request #4650 from coralproject/release-9.1.2
tessalt Jul 18, 2024
a326807
Merge branch 'main' into develop
tessalt Jul 18, 2024
e0c7cfd
Merge pull request #4651 from coralproject/develop
tessalt Jul 18, 2024
c64ce95
stack tenor gif results tightly in a cascade grid
nick-funk Jul 27, 2024
921a71b
flex center tenor gif search result images
nick-funk Jul 27, 2024
426039d
set padding on grid items
nick-funk Jul 31, 2024
a8a00f7
Merge pull request #4653 from coralproject/feat/tenor-cascade-grid
tessalt Aug 6, 2024
546358a
Merge pull request #4641 from coralproject/feat/CORL-3174-external-be…
tessalt Aug 6, 2024
e51a528
update package
tessalt Aug 6, 2024
9e4908e
Merge pull request #4655 from coralproject/release-9.2.0
tessalt Aug 6, 2024
91a49de
Merge branch 'main' into develop
tessalt Aug 6, 2024
1993320
optimize mget performance on counts v2 endpoint
nick-funk Sep 10, 2024
1fe0936
refactor: computeCountKey helper function
nick-funk Sep 10, 2024
2c1faf4
document the counts v2 endpoint
nick-funk Sep 10, 2024
c45d123
add optional `mongoCount` to v2 counts endpoint
nick-funk Sep 10, 2024
7c66b28
add comments to v2 counts endpoint result type
nick-funk Sep 10, 2024
ce25264
document returning null for not found storyID's
nick-funk Sep 10, 2024
c9e6ddf
Merge branch 'develop' into feat/CORL-3172-optimized-redis-query
nick-funk Sep 10, 2024
100927c
Revert "Merge branch 'develop' into feat/CORL-3172-optimized-redis-qu…
nick-funk Sep 10, 2024
aadc77c
Merge branch 'feat/CORL-3172-counts-endpoint' into feat/CORL-3172-opt…
nick-funk Sep 10, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
115 changes: 80 additions & 35 deletions server/src/core/server/app/handlers/api/story/count.ts
Original file line number Diff line number Diff line change
Expand Up @@ -187,6 +187,17 @@ async function calculateStoryCount(

export type CountV2Options = Pick<AppOptions, "mongo" | "redis">;

interface CountResult {
storyID: string;
redisCount?: number; // set if count came from redis
mongoCount?: number; // set if count came from mongo
count: number; // always set, can come from mongo or redis
}

export const computeCountKey = (tenantID: string, storyID: string) => {
return `${tenantID}:${storyID}:count`;
};

export const countsV2Handler =
({ mongo, redis }: CountV2Options): RequestHandler<TenantCoralRequest> =>
async (req, res, next) => {
Expand All @@ -199,42 +210,76 @@ export const countsV2Handler =

const { storyIDs }: CountsV2Body = validate(CountsV2BodySchema, req.body);

const storyCounts = await Promise.all(
storyIDs.map(async (storyID) => {
// check that cache is available

// try to look in Redis cache here first by key
const key = `${tenant.id}:${storyID}:count`;
const redisCount = await redis.get(key);

if (redisCount) {
logger.debug("found story count for counts v2 in redis cache", {
storyID,
redisCount,
});
return { storyID, redisCount };
} else {
const count = await retrieveStoryCommentCounts(
mongo,
tenant.id,
storyID
);

// add count to Redis cache here then return
await redis.set(key, count, "EX", COUNTS_V2_CACHE_DURATION);
logger.debug("set story count for counts v2 in redis cache", {
storyID,
count,
});

return {
storyID,
count,
};
}
})
// grab what keys we can that are already in Redis with one bulk call
const redisCounts = await redis.mget(
...storyIDs.map((id) => computeCountKey(tenant.id, id))
Copy link
Contributor Author

@nick-funk nick-funk Sep 10, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

redis really likes it when you ask for everything all at once, its scheduler is great at grabbing n-many keys and returning it in a fast serialized payload!

);
res.send(JSON.stringify(storyCounts));

// quickly iterate over our results and see if we're missing any of the
// values for our requested story id's
const countResults = new Map<string, CountResult>();
const missingIDs: string[] = [];
for (let i = 0; i < storyIDs.length; i++) {
const storyID = storyIDs[i];
const redisCount = redisCounts[i];

if (redisCount !== null && redisCount !== undefined) {
try {
const count = parseInt(redisCount, 10);
countResults.set(storyID, { storyID, redisCount: count, count });
} catch {
missingIDs.push(storyID);
}
} else {
missingIDs.push(storyID);
}
}

// compute out the counts for any story id's we couldn't
// get a count from Redis
for (const missingID of missingIDs) {
const count = await retrieveStoryCommentCounts(
mongo,
tenant.id,
missingID
);

const key = computeCountKey(tenant.id, missingID);
await redis.set(key, count, "EX", COUNTS_V2_CACHE_DURATION);
logger.debug("set story count for counts v2 in redis cache", {
storyID: missingID,
count,
});

countResults.set(missingID, {
storyID: missingID,
mongoCount: count,
count,
});
}

// strictly follow the result set based on the story id's
// we were given from the caller. Then return the values
// from our combined redis/mongo results.
//
// this means if a user asked for id's ["1", "2", "3", "does-not-exist", "1"], they would
// receive counts like so:
// [
// { storyID: 1, redisCount: 2, count: 2 },
// { storyID: 2, redisCount: 5, count: 5 },
// { storyID: 3, mongoCount: 2, count: 2 },
// null,
// { storyID: 1, redisCount: 2, count: 2 }
// ]
//
// many of our counts endpoints appreciate this adherence.
const results: Array<CountResult | null> = [];
for (const storyID of storyIDs) {
const value = countResults.get(storyID) ?? null;
results.push(value);
}

res.send(JSON.stringify(results));
} catch (err) {
return next(err);
}
Expand Down
Loading