DylanDev
DylanDev•3mo ago

Clerk With Convex in Backend Functions

I want to store a score variable in the public metadata but I can't figure out how to modify that from the backend and I get an error? Error:
Uncaught Error
at UserAPI.request (../node_modules/@clerk/backend/src/api/request.ts:186:15)
at async handler (../convex/game.ts:102:61)
Uncaught Error
at UserAPI.request (../node_modules/@clerk/backend/src/api/request.ts:186:15)
at async handler (../convex/game.ts:102:61)
Code:
import { v } from "convex/values";

import { mutation, query } from "./_generated/server";
import { createClerkClient } from '@clerk/backend';

const clerkClient = createClerkClient({ secretKey: process.env.CLERK_SECRET_KEY });

...

export const checkGuess = mutation({
args: { id: v.id("levels"), guessLatitude: v.float64(), guessLongitude: v.float64() },
handler: async(ctx, args) => {
const level = await ctx.db.get(args.id);

if(!level) {
throw new Error("No levels exist");
}

const correctLat = level.latitude;
const correctLng = level.longitude;

const distanceAway = parseInt(haversineDistanceInFeet(correctLat, correctLng, args.guessLatitude, args.guessLongitude).toFixed(0));
// give some leniency to the distance
let lenientDistance = distanceAway - 20;
if (lenientDistance < 0) {
lenientDistance = 0;
}
// If within 250 feet, score increases by distance if outside of 250 feet score = 0
let score = 250 - lenientDistance;
if (score < 0) { // no negative score
score = 0;
}

// Fetch the user from Clerk
const user = await ctx.auth.getUserIdentity();
if(user !== null) {
console.log(user); // THIS IS PRINTING OUT CORRECTLY
await clerkClient.users.updateUser(user.subject, {
publicMetadata: {
score: score,
},
});
}

return {
correctLat,
correctLng,
distanceAway,
score,
}
}
});
import { v } from "convex/values";

import { mutation, query } from "./_generated/server";
import { createClerkClient } from '@clerk/backend';

const clerkClient = createClerkClient({ secretKey: process.env.CLERK_SECRET_KEY });

...

export const checkGuess = mutation({
args: { id: v.id("levels"), guessLatitude: v.float64(), guessLongitude: v.float64() },
handler: async(ctx, args) => {
const level = await ctx.db.get(args.id);

if(!level) {
throw new Error("No levels exist");
}

const correctLat = level.latitude;
const correctLng = level.longitude;

const distanceAway = parseInt(haversineDistanceInFeet(correctLat, correctLng, args.guessLatitude, args.guessLongitude).toFixed(0));
// give some leniency to the distance
let lenientDistance = distanceAway - 20;
if (lenientDistance < 0) {
lenientDistance = 0;
}
// If within 250 feet, score increases by distance if outside of 250 feet score = 0
let score = 250 - lenientDistance;
if (score < 0) { // no negative score
score = 0;
}

// Fetch the user from Clerk
const user = await ctx.auth.getUserIdentity();
if(user !== null) {
console.log(user); // THIS IS PRINTING OUT CORRECTLY
await clerkClient.users.updateUser(user.subject, {
publicMetadata: {
score: score,
},
});
}

return {
correctLat,
correctLng,
distanceAway,
score,
}
}
});
15 Replies
Convex Bot
Convex Bot•3mo ago
Thanks for posting in <#1088161997662724167>. Reminder: If you have a Convex Pro account, use the Convex Dashboard to file support tickets. - Provide context: What are you trying to achieve, what is the end-user interaction, what are you seeing? (full error message, command output, etc.) - Use search.convex.dev to search Docs, Stack, and Discord all at once. - Additionally, you can post your questions in the Convex Community's <#1228095053885476985> channel to receive a response from AI. - Avoid tagging staff unless specifically instructed. Thank you!
FleetAdmiralJakob 🗕 🗗 🗙
You cant make a request inside a mutation you need an action for that
DylanDev
DylanDevOP•3mo ago
are you able to provide me with any documentation? I was having trouble finding info on it
FleetAdmiralJakob 🗕 🗗 🗙
Actions | Convex Developer Hub
Actions can call third party services to do things such as processing a payment
FleetAdmiralJakob 🗕 🗗 🗙
only actions can access the internet
DylanDev
DylanDevOP•3mo ago
ah okay Thank you 👑
DylanDev
DylanDevOP•3mo ago
@FleetAdmiralJakob 🗕 🗗 🗙 So do I have to have a httpAction api function that my other function calls? im just a little bit confused on how to implement this
FleetAdmiralJakob 🗕 🗗 🗙
you actually dont need an httpAction just a normal action. your other functions call this action then httpAction is when you want to call your functions from a webhook or a custom client.
DylanDev
DylanDevOP•3mo ago
ah okay @FleetAdmiralJakob 🗕 🗗 🗙 Have you used clerk before? Are you at all expierenced with messing with it from the backend
FleetAdmiralJakob 🗕 🗗 🗙
Yeah I use Clerk + Convex and there are a few questions to be answered and problems to be solved One question for example is where do I want to store user data. Both Clerk and Convex offer to store User data. There are three options: In Convex, in Clerk, try to sync both so it doesn't matter but Convex is faster For myself I found that it's the easiest to only use Clerk for Auth and store user data in Convex but try to keep both in sync but the source of truth stays Convex Other problems I had was with the signup flow. I wanted a custom username schema. Clerk doesn't offer this type of thing so I had to sent all the credentials to my server first and sign up and create the user from there for example
DylanDev
DylanDevOP•3mo ago
Ah i see i just need something simple where each user can have stats stored about them i think using meta data in clerk would be fine but im trying to decide
FleetAdmiralJakob 🗕 🗗 🗙
If you store it in metadata in Clerk then u need actions for everything and querying from Clerk will take longer than from Convex
sshader
sshader•3mo ago
Check out https://docs.convex.dev/auth/database-auth if you haven't already -- it goes over a few strategies for syncing over data from Clerk to Convex. As y'all are mentioning, it's technically possible to make everything an action and always request the user data from Clerk, but then you lose out on many of the benefits on Convex (no realtime updates, no automatic caching)
Storing Users in the Convex Database | Convex Developer Hub
_If you're using Convex Auth the user information
DylanDev
DylanDevOP•3mo ago
@sshader @FleetAdmiralJakob 🗕 🗗 🗙 alright i see ill look into it thank you so much!