Starlord
Starlord•2mo ago

query cache on the server side

would be great to have query cache on the server side so static data doesnt cause billing increase
52 Replies
ballingt
ballingt•2mo ago
Could you say more out this? like if your server functions fetch("http://weather.gov") repeatedly, you want that cached?
Starlord
StarlordOP•2mo ago
hey, no
const item = await db
.query("items")
.filter(q => q.eq(q.field("name"), itemName))
.first();
const item = await db
.query("items")
.filter(q => q.eq(q.field("name"), itemName))
.first();
ballingt
ballingt•2mo ago
I don't understand what a query cache is
Starlord
StarlordOP•2mo ago
i have items in the database. i dont wan to fetch them every request
ballingt
ballingt•2mo ago
you want these cached between requests?
Starlord
StarlordOP•2mo ago
yes
ballingt
ballingt•2mo ago
for speed? cost?
Starlord
StarlordOP•2mo ago
well mostly cost.
ballingt
ballingt•2mo ago
What do you mean by static here
Starlord
StarlordOP•2mo ago
this datatable doesnt change it has always static data
ballingt
ballingt•2mo ago
if it never changes it maybe shouldn't be in the database? well fine to put there, but what's an example of when this would happen?
Starlord
StarlordOP•2mo ago
well it should be in database because it should be possible to change it by admin add new items for example
ballingt
ballingt•2mo ago
and when does that invalidate that sounds like normal database data then
Starlord
StarlordOP•2mo ago
well this is database data that nearly neve changes and would be great to have cache for it that can be invalidated
ballingt
ballingt•2mo ago
ok that makes sense in some systems, in COnvex that's just already how the databse works the database is just about as efficient as any cache we'd build, it's right there in Convex your functions run "inside the database"
Starlord
StarlordOP•2mo ago
well those calls still affect the limits as far i know
ballingt
ballingt•2mo ago
ah yeah all of this affects limits
Starlord
StarlordOP•2mo ago
ok i understand
ballingt
ballingt•2mo ago
if you have a specific use case I'd love to hear, often writing something with Convex will change this somewhat You can embed a little data in your function code, that's a bit like what you want
Starlord
StarlordOP•2mo ago
this would be great to generate static code based on item ids then when convex is deployed. but probably asking too much here 🙂
const ITEM_ID_MAPPING = {
[ItemNames.Coins]: "YOUR_COINS_ID_HERE",
[ItemNames.Spins]: "YOUR_SPINS_ID_HERE",
[ItemNames.Ticket]: "YOUR_TICKET_ID_HERE",
// ... other items
} as const;
const ITEM_ID_MAPPING = {
[ItemNames.Coins]: "YOUR_COINS_ID_HERE",
[ItemNames.Spins]: "YOUR_SPINS_ID_HERE",
[ItemNames.Ticket]: "YOUR_TICKET_ID_HERE",
// ... other items
} as const;
right now i have always to look for item by name / id
ballingt
ballingt•2mo ago
I think you should try building this using the database, then if you have performance issues that's the thing to talk about I think you're looking for a solution that was useful to you in a different environment, a traditional backend where your code runs far from your database
this would be great to generate static code based on item ids then when convex is deployed. but probably asking too much here 🙂
I don't quite follow here
Starlord
StarlordOP•2mo ago
performance will depend on user amount. because functions execute every 3 seconds sometimes per user than means 1 millions users could hit all limits very quick
ballingt
ballingt•2mo ago
send me an email laying out your architecture concerns here, it's hard when it's theoretical and there are some real use cases that are difficult, but we find they come up rarely tom@convex.dev it sounds like you've built things before and run into limits, I'm curious if you'll have those same issues on COnvex
Starlord
StarlordOP•2mo ago
export async function hasEnoughCoins(
ctx: { db: DatabaseReader },
userId: Id<"users">,
requiredAmount: number
): Promise<boolean> {

const coinsItemId = await getItemIdByName(ctx, ItemNames.Coins);
const coins = await getItemAmount(ctx, userId, coinsItemId);
return coins >= requiredAmount;
}

export async function getItemIdByName(
ctx: { db: DatabaseReader },
itemName: ItemNames,
): Promise<Id<"items">> {

const { db } = ctx;
const item = await db
.query("items")
.filter(q => q.eq(q.field("name"), itemName))
.first();

if (!item) {
throw new Error(`Item not found: ${itemName}`);
}

return item._id;
}
export async function hasEnoughCoins(
ctx: { db: DatabaseReader },
userId: Id<"users">,
requiredAmount: number
): Promise<boolean> {

const coinsItemId = await getItemIdByName(ctx, ItemNames.Coins);
const coins = await getItemAmount(ctx, userId, coinsItemId);
return coins >= requiredAmount;
}

export async function getItemIdByName(
ctx: { db: DatabaseReader },
itemName: ItemNames,
): Promise<Id<"items">> {

const { db } = ctx;
const item = await db
.query("items")
.filter(q => q.eq(q.field("name"), itemName))
.first();

if (!item) {
throw new Error(`Item not found: ${itemName}`);
}

return item._id;
}
here is example of my code. and function like hasEnoughCoins is requested every time. so would be great to have itemid - name mapping
ballingt
ballingt•2mo ago
ah you could just put this in your code yeah?
Starlord
StarlordOP•2mo ago
you mean itemid - name mapping? yes. but its manual work
ballingt
ballingt•2mo ago
I'm not following, manual work? Either you have to (manually? or write a script) add them all to the database, or you have to (manually? or write a script) add them to your code
Starlord
StarlordOP•2mo ago
const ITEM_ID_MAPPING = {
[ItemNames.Coins]: "YOUR_COINS_ID_HERE",
[ItemNames.Spins]: "YOUR_SPINS_ID_HERE",
[ItemNames.Ticket]: "YOUR_TICKET_ID_HERE",
// ... other items
} as const;
const ITEM_ID_MAPPING = {
[ItemNames.Coins]: "YOUR_COINS_ID_HERE",
[ItemNames.Spins]: "YOUR_SPINS_ID_HERE",
[ItemNames.Ticket]: "YOUR_TICKET_ID_HERE",
// ... other items
} as const;
structure like this would have to be maintained for every item its fine if those are not much items. but if it s a game those are a lot of items
ballingt
ballingt•2mo ago
like how many megabytes?
Starlord
StarlordOP•2mo ago
right now its not big. its not megabytes for sure anyway i will go with code mapping solution for now 🙂
ballingt
ballingt•2mo ago
In convex your options are - embed the data in your code: keep your code under a few MB and you're fine - store it in the database: the database is very fast to access from Convex functions - store it in Convex file storage or an external file storage, you'll have to download it each time you need it, slow
Starlord
StarlordOP•2mo ago
yes just was looking for way to reduce amount of calls to the database
ballingt
ballingt•2mo ago
if it's less than a few kilobytes then stick it in your code, I think esbuild will bundle .txt files and .json files too so you don't have to write it out as TypeScript
Starlord
StarlordOP•2mo ago
ok thanks
ballingt
ballingt•2mo ago
or really if it's less than a MB or two generate the JSON from your source of truth and import that in your code
Starlord
StarlordOP•2mo ago
right now its not big. just looking for future where its larger
ballingt
ballingt•2mo ago
if it doesn't change quickly, embedding data in your code is the cache you're looking for bundlers like esbuild (what Convex uses) do a good job letting you include lots of things in the bundle
Starlord
StarlordOP•2mo ago
yes so writing a script that would generate embedding data based on convex database
ballingt
ballingt•2mo ago
oh it's already in the DB?
Starlord
StarlordOP•2mo ago
yes its already in convex table
ballingt
ballingt•2mo ago
hm I see you're really just trying to save on costs yeah this works then consider building it the easy way first and checking how your costs are doing, there's a lot of optimizing too early you can do — but if you've built things like this before and have a good guess at the limits you'll hit, sounds good
Starlord
StarlordOP•2mo ago
consider adding something like this out of the box to convex maybe in future. to pregenerate embedding data based on database tables. i see a lot of apps would need something like this for example app for configuration
ballingt
ballingt•2mo ago
Generally I'd prefer to make using the database cheap and fast; it really is faster than you think!
Starlord
StarlordOP•2mo ago
yes sure thanks for help btw i mage solidjs work with convex by porting react code. do you have any use for it?
Starlord
StarlordOP•2mo ago
the only thing. i had to make ugly imports from npm module because it did not provide exports for some types
No description
ballingt
ballingt•2mo ago
We've heard of a few of these wrappers, definitely interested in this existing! @convex_dev_module is convex auth?
Starlord
StarlordOP•2mo ago
yes
ballingt
ballingt•2mo ago
cool, wanna open an issue on https://github.com/get-convex/convex-auth about us exporting those types? probably no reason not to
Starlord
StarlordOP•2mo ago
but this code is working currently by integrating it directly into project code
ballingt
ballingt•2mo ago
thanks ah well eventually it'd be great to a library for it! otherwise if it's open source, posting it to e.g. #show-and-tell would be cool (and even if it's not open source, still very cool to post! But re Solid, if it's open it'd be cool to point people toward this)
Starlord
StarlordOP•2mo ago
GitHub
expose SignInAction and SignOutAction for export · Issue #132 · ge...
Currently, the SignInAction and SignOutAction types need to be imported from the internal implementation path: ./node_modules/@convex-dev/auth/src/server/implementation/index.js This is problematic...
Starlord
StarlordOP•2mo ago
ok i will post source code of solidjs plugin later

Did you find this page helpful?