-
Notifications
You must be signed in to change notification settings - Fork 25
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
feat: d1 adapter for the tag cache #320
base: main
Are you sure you want to change the base?
Conversation
🦋 Changeset detectedLatest commit: 54a89cb The changes in this PR will be included in the next version bump. This PR includes changesets to release 1 package
Not sure what this means? Click here to learn what changesets are. Click here if you're a maintainer who wants to add another changeset to this PR |
01d1c68
to
d0d0738
Compare
commit: |
d0d0738
to
1cce4af
Compare
* | ||
* The mapping creates an index of each tags pointing to its paths, and each path pointing to its tags. | ||
*/ | ||
export function extractCacheAssetsManifest(buildOpts: BuildOptions) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We already compute all the tags and cache in the aws adapter https://github.com/opennextjs/opennextjs-aws/blob/14b81827f9078b98e32115fb5cfe706d03d64537/packages/open-next/src/build/createAssets.ts#L159-L239
BTW you are missing the fetch cache here
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks, I didn't realise the manifest was already generated. I'll change it to use that
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is resolved, right?
// inlined during build | ||
const manifest = process.env.__OPENNEXT_CACHE_TAGS_MANIFEST; | ||
|
||
class D1TagCache implements TagCache { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not sure that D1 is the right fit for this. The tag cache has been designed around DynamoDB and its strength/limitation.
I'm introducing a new mode for the tag cache that would probably better fit an SQL db opennextjs/opennextjs-aws#717
I think that what would make the most sense would be either using D1 with the new mode (and it avoids having to prepopulate anything) or using this mode with KV (But this would probably mean duplicating some data in KV)
Another thing is that if i'm not mistaken D1 is regional, but the tag cache will be reached from all over the world (And the fetch cache could be used in SSR request as well )
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not sure KV would really work that well due to its eventually consistent nature - you get up to 60 seconds on entries continuing to be polled, and if you use a <5 min revalidation time, it essentially becomes pointless trying to use a cache IMO.
D1 is regional yeah - means a little more latency for some regions.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I can rework this PR to be based on the new mode if that makes most sense.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For the new mode there is benefits and drawbacks, one option could be to implement both mode so that each user could use the one that is better suited for them.
@vicb @dario-piotrowicz What do you think about that ? For reference here is the issue explaining the 2 mode and their benefits/drawback opennextjs/opennextjs-aws#706
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
+1 to have the 2 modes if it's not too much dev & maintenance vs the benefits.
We can also merge a single mode when it's ready and implement the other mode later.
401843a
to
69f2d20
Compare
229b2e2
to
fa3b420
Compare
69f2d20
to
3566d04
Compare
|
||
try { | ||
const { success, results } = await db | ||
.prepare(`SELECT tag FROM ${table} WHERE path = ?`) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
can't we use bind for the table name? (SQL injection)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Unfortunately not - it gives a syntax error. The table is driven by an env var, so i wouldnt think sql injection will be a problem
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It should not... but maybe we can hardcode tags
here anyway.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I did this with the idea that people might want to use a different table name (multiple projects using same db), so it was using the env var and defaulting to tags
if not present. I can change to always hardcode to tags if you want, but I feel like it's a useful bit of configurability to have?
@@ -112,6 +113,7 @@ export async function bundleServer(buildOpts: BuildOptions): Promise<void> { | |||
"process.env.NEXT_RUNTIME": '"nodejs"', | |||
"process.env.NODE_ENV": '"production"', | |||
"process.env.NEXT_MINIMAL": "true", | |||
"process.env.__OPENNEXT_CACHE_TAGS_MANIFEST": `${JSON.stringify(extractCacheAssetsManifest(buildOpts))}`, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@conico974 do you think this could be added to the config adapter?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You mean the open-next.config.ts
? Not sure how it would work since it is bundled before next build
One thing about inlining the manifest here is that this could become pretty big, especially for website with a lot of page.
For example the __NT_/layout
tag is on every page.
Inlining this will likely become an issue at scale
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I was thinking about adapter/config
but the size issue would be the same.
So we should preload the DB?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Would it be possible to generate a SQL file instead and run wrangler execute as part of the deployment ? This seems like a better idea
Or maybe using the rest API with the initialization function from OpenNext
3566d04
to
0c28284
Compare
* The mapping creates an index of each tags pointing to its paths, and each path pointing to its tags. | ||
*/ | ||
export function extractCacheAssetsManifest(options: BuildOptions): CacheAssetsManifest { | ||
// TODO: Expose the function for getting this data as an adapter-agnostic utility in AWS. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That's kind of the point of the initializationFunction
https://opennext.js.org/aws/inner_workings/components/initializer
With a custom wrapper and a custom tag cache it could be turned into a function.
Not entirely sure it's worth it though
c8bc9f0
to
79bab94
Compare
79bab94
to
54a89cb
Compare
This PR is stacked on top of the changes in #319.
Docs PR - opennextjs/docs#66