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

[front] Improve log with multiple memberships, use concurrent execution #10390

Closed
wants to merge 3 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
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
80 changes: 33 additions & 47 deletions front/admin/relocate_users.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import { removeNulls } from "@dust-tt/types";
import type { ApiResponse } from "auth0";
import { concurrentExecutor, removeNulls } from "@dust-tt/types";

import { getAuth0ManagemementClient } from "@app/lib/api/auth0";
import { getAuth0ManagemementClient, throttleAuth0 } from "@app/lib/api/auth0";
import { SUPPORTED_REGIONS } from "@app/lib/api/regions/config";
import { Authenticator } from "@app/lib/auth";
import { MembershipResource } from "@app/lib/resources/membership_resource";
Expand Down Expand Up @@ -34,32 +33,6 @@ makeScript(
const auth = await Authenticator.internalAdminForWorkspace(workspaceId);
const workspace = auth.getNonNullableWorkspace();

let remaining = 10;
let resetTime = Date.now();

const throttleAuth0 = async <T>(fn: () => Promise<ApiResponse<T>>) => {
if (remaining < rateLimitThreshold) {
const now = Date.now();
const waitTime = resetTime * 1000 - now;
logger.info({ waitTime }, "Waiting");
await new Promise((resolve) => setTimeout(resolve, waitTime));
}

const res = await fn();
if (res.status !== 200) {
logger.error({ res }, "When calling Auth0");
process.exit(1);
}

remaining = Number(res.headers.get("x-ratelimit-remaining"));
resetTime = Number(res.headers.get("x-ratelimit-reset"));

const limit = Number(res.headers.get("x-ratelimit-limit"));
logger.info({ limit, remaining, resetTime }, "Rate limit");

return res.data;
};

const members = await MembershipResource.getMembershipsForWorkspace({
workspace,
});
Expand All @@ -70,8 +43,13 @@ makeScript(
(m) => m.workspaceId !== workspace.id
);
if (externalMemberships.length > 0) {
const userIds = externalMemberships.map((m) => m.userId);
const users = await UserResource.fetchByModelIds(userIds);
logger.error(
{ users: externalMemberships.map((m) => m.user) },
{
externalMemberships,
users: users.map((u) => ({ sId: u.sId, email: u.email })),
},
"Some users have mutiple memberships"
);
process.exit(1);
Expand All @@ -84,23 +62,31 @@ makeScript(

let count = 0;

for (const auth0Id of auth0Ids) {
count++;
logger.info({ user: auth0Id, count }, "Setting region");
if (execute) {
await throttleAuth0(() =>
managementClient.users.update(
{
id: auth0Id,
},
{
app_metadata: {
region: destinationRegion,
},
}
)
);
await concurrentExecutor(
auth0Ids,
async (auth0Id) => {
count++;
logger.info({ user: auth0Id, count }, "Setting region");
if (execute) {
await throttleAuth0(
() =>
managementClient.users.update(
{
id: auth0Id,
},
{
app_metadata: {
region: destinationRegion,
},
}
),
{ rateLimitThreshold }
);
}
},
{
concurrency: 10,
}
}
);
}
);
31 changes: 31 additions & 0 deletions front/lib/api/auth0.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import type { Session } from "@auth0/nextjs-auth0";
import type { Result } from "@dust-tt/types";
import { Err, Ok } from "@dust-tt/types";
import type { ApiResponse } from "auth0";
import { ManagementClient } from "auth0";
import { isLeft } from "fp-ts/lib/Either";
import * as t from "io-ts";
Expand Down Expand Up @@ -266,3 +267,33 @@ export async function getAuth0UsersFromEmail(emails: string[]) {

return auth0Users;
}

const throttleAuth0State = {
remaining: -1,
resetTime: 0,
};

export const throttleAuth0 = async <T>(
fn: () => Promise<ApiResponse<T>>,
{ rateLimitThreshold }: { rateLimitThreshold: number }
) => {
const { remaining, resetTime } = throttleAuth0State;
if (remaining !== -1 && remaining < rateLimitThreshold) {
const now = Date.now();
const waitTime = resetTime * 1000 - now;
await new Promise((resolve) => setTimeout(resolve, waitTime));
}

const res = await fn();
if (res.status !== 200) {
logger.error({ res }, "When calling Auth0");
process.exit(1);
}

throttleAuth0State.remaining = Number(
res.headers.get("x-ratelimit-remaining")
);
throttleAuth0State.resetTime = Number(res.headers.get("x-ratelimit-reset"));

return res.data;
};