How do I gracefully disconnect MongoDB in Google Functions? Behavior of "normal" Cloud Run and "Functions Cloud Run" seems to be different

huangapple go评论58阅读模式
英文:

How do I gracefully disconnect MongoDB in Google Functions? Behavior of "normal" Cloud Run and "Functions Cloud Run" seems to be different

问题

在正常的Cloud Run中,以下代码似乎可以正确关闭Mongoose/MongoDB连接。

const cleanup = async () => {
    await mongoose.disconnect()
    console.log('database | disconnected from db')
    process.exit()
}

const shutdownSignals = ['SIGTERM', 'SIGINT']
shutdownSignals.forEach((sig) => process.once(sig, cleanup))

但是对于由Cloud Functions管理的Cloud Run,似乎情况不同。实例会在发送SIGTERM后不等待通常的10秒,这是“正常”Cloud Run在SIGTERM发送后通常会等待的时间,因此我从未看到database | disconnected from db

如何解决这个问题?我不想为每个Cloud Functions调用创建一个连接(在我的情况下非常浪费资源)。

英文:

In a normal Cloud Run something like the following seems to properly close a Mongoose/MongoDB connection.

const cleanup = async () => {
    await mongoose.disconnect()
    console.log('database | disconnected from db')
    process.exit()
}

const shutdownSignals = ['SIGTERM', 'SIGINT']
shutdownSignals.forEach((sig) => process.once(sig, cleanup))

But for a Cloud-Functions-managed Cloud Run this seems not to be the case. The instances shut down without waiting the usual 10s that "normal" Cloud Runs give after the SIGTERM is sent, so I never see the database | disconnected from db.

How would one go about this? I don't wanna create a connection for every single Cloud Functions call (very wasteful in my case).

答案1

得分: 0

以下是您要翻译的内容:

Well, here is what I went with for now:

    import mongoose from 'mongoose'
    import { Sema } from 'async-sema'

    functions.cloudEvent('someCloudFunction', async (event) => {
        await connect()
    
        // actual computation here
    
        await disconnect()
    })
    
    const state = {
        num: 0,
        sema: new Sema(1),
    }

    export async function connect() {
        await state.sema.acquire()
        if (state.num === 0) {
            try {
                await mongoose.connect(MONGO_DB_URL)
            } catch (e) {
                process.exit(1)
            }
        }
        state.num += 1
        state.sema.release()
    }
    
    export async function disconnect() {
        await state.sema.acquire()
        state.num -= 1
        if (state num === 0) {
            await mongoose.disconnect()
        }
        state.sema.release()
    }

As one can see I used kind of a "reference counting" of the processes which want to use the connection, and ensured proper concurrency with `async-sema`.

I should note that this works well with the setup I have; I allow many concurrent requests to one of my Cloud Functions instances. In other cases this solution might not improve over just opening up (and closing) a connection every single time the function is called. But as stuff like https://cloud.google.com/functions/docs/writing/write-event-driven-functions#termination seems to imply, everything has to be handled inside the cloudEvent function.

请注意,我已将代码部分翻译成中文。如果您有任何其他需要,请告诉我。

英文:

Well, here is what I went with for now:

import mongoose from 'mongoose'
import { Sema } from 'async-sema'
functions.cloudEvent('someCloudFunction', async (event) => {
await connect()
// actual computation here
await disconnect()
})
const state = {
num: 0,
sema: new Sema(1),
}
export async function connect() {
await state.sema.acquire()
if (state.num === 0) {
try {
await mongoose.connect(MONGO_DB_URL)
} catch (e) {
process.exit(1)
}
}
state.num += 1
state.sema.release()
}
export async function disconnect() {
await state.sema.acquire()
state.num -= 1
if (state.num === 0) {
await mongoose.disconnect()
}
state.sema.release()
}

As one can see I used kind of a "reference counting" of the processes which want to use the connection, and ensured proper concurrency with async-sema.

I should note that this works well with the setup I have; I allow many concurrent requests to one of my Cloud Functions instances. In other cases this solution might not improve over just opening up (and closing) a connection every single time the function is called. But as stuff like https://cloud.google.com/functions/docs/writing/write-event-driven-functions#termination seems to imply, everything has to be handled inside the cloudEvent function.

huangapple
  • 本文由 发表于 2023年2月8日 18:27:10
  • 转载请务必保留本文链接:https://go.coder-hub.com/75384406.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定