Firebase Admin SDK更新用户时超出了配额限制 - 我该如何请求更多配额?

16
我们尝试在我们的多租户设置中更新许多用户,当整个租户需要启用/禁用时。由于这一点,我们有时会遇到QUOTA_EXCEEDED错误,特别是对于具有许多用户的大型租户。我已经在此处询问了如何更好地执行此操作。
由于Firebase Admin SDK当前没有批量操作来更新用户,那么我该如何请求配额提高呢? 我该如何提高配额?
3个回答

15

对于所有遇到同样问题的人,这里提供一个解决方案。

我联系了Firebase支持团队并获得了以下回答:

如果您试图一次性更新多个用户的信息(每秒超过10个用户或请求),则会出现以下错误消息:“超出更新帐户信息的配额”。请注意,在短时间内收到大量请求时,我们会自动应用节流以保护我们的服务器。您可以尝试依次发送请求(分发负载)而不是同时发送它们。因此,基本上,您需要逐个处理它们(而不是全部一次性处理),以避免出现错误。

所以我通过设置一个时间间隔为100毫秒的超时器来解决这个问题,每次只发送一条记录。

function listAllUsers(nextPageToken) {
        let timeout = 0;
        admin.auth().listUsers(1000, nextPageToken)
            .then(function (listUsersResult) {
                listUsersResult.users.forEach(function (userRecord) {
                    timeout = timeout + 100
                    nextUser(userRecord.uid, timeout)
                });
                if (listUsersResult.pageToken) {
                    listAllUsers(listUsersResult.pageToken);
                }
            })
            .catch(function (error) {
                console.log('Error listing users:', error);
            });
    }
    listAllUsers();
下一个用户函数:
function nextUser(uid, timeout) { 
        setTimeout(() => {
            admin.auth().setCustomUserClaims(uid, { client: true }).then(() => {
            }).catch(function (error) {
                console.log('Error setting user:', error);
            });
        }, timeout);
    }

代码可以运行,我更新了所有用户而没有配额错误。但是在所有用户被处理后,函数仍然挂起,我需要手动终止它。 - Deviling Master
1
发现100毫秒有点太紧了,偶尔会出现限制,因此可能需要多留一点时间,以避免在完成90%的处理后捕获错误而不得不重新处理。 - Rich Andrews
如果你有时间的话,500毫秒可以无错误地工作~ - David
我收到了错误信息:Promises必须使用类似于这样的代码适当地处理。 - MadMac

7

在这里,我是Firebaser

如果您遇到无法从Firebase控制台更改的配额限制,请联系Firebase支持团队以获得个性化帮助。他们通常可以帮助暂时提高配额,并且这也是我们工程团队需要某项功能的重要指标。


13
这个用户更新的配额在授权限制文档中没有提到。对于开发人员来说,提前了解默认限制将有助于计划和优化使用情况。我必须联系支持团队以获取生成电子邮件链接的限制信息。 - Umar Hussain
1
刚刚开始处理这个问题,我想再次强调对于这个限制需要更好的文档说明。虽然我们没有那么多用户,但是很多人恰好在同一个下午加入了我们。当我们达到这个限制并进行研究时,很多东西都出了问题。拥有一个关键功能,却有着隐蔽的配额和手动帮助步骤是不好的。 - bsplosion

3

在为所有用户更新自定义认证声明时,我遇到了上面提到的相同问题。通过这种替代的顺序运行更新的实现,我能够解决它,而不依赖于超时。

这个方法会等待前一个承诺解决后再执行下一个更新。

try {
    const promises = await IterateAllUsers();
    await promises.reduce(async (previousPromise, nextAsyncFunctionPromise) => {
        await previousPromise;
        const nextAsyncFunction = await nextAsyncFunctionPromise
        // Actual execution
        await nextAsyncFunction();
    }, Promise.resolve());
    console.log('done');
} catch(error) {
    console.error(error);
}

无论您需要迭代的内容是什么,它都应该至少返回一组 Promise 函数,以便稍后执行。
async function IterateAllUsers(): Promise<Array<Promise<Function>>> {
    const promises: Array<Promise<Function>> = [];
    await // Iterate Authentication Users or Database Collection etc.
    promises.push(updateAuthCustomClaims(user.key, someValue));    
    return Promise.resolve(promises);
}

用于填充数组以后执行任务的高阶函数。
async function updateAuthCustomClaims(uid: string, someValue): Promise<Function> {
    return async () => {
        try {
            await admin.auth().setCustomUserClaims(uid,{someValue});
            console.log('Updated user: ', uid);
        } catch(error) {
            console.warn('Could not add custom claim due to: ', error);
        }
        return Promise.resolve();
    };
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接