所以,让我简要介绍一下我试图实现的目标。我有一个名为apply
的命令,只要有人输入该命令,应用函数就会开始执行。现在,application函数有一些代码部分,我想同时执行,以防许多用户同时触发该命令,还有一个名为register
的异步函数,我想一次执行一次。以下是代码的一瞥:
@client.command()
async def apply(ctx):
#Stuff I want to be run concurrently
await register(ctx.author)
async def register(user):
# I've an another python file 'db.py' for accessing the database
data = await db.execute_query('SELECT Total_Reg from Data WHERE rowid = 1')
total = data[0][0] # Getting the total registrations value and storing it in total variable
if total >= max_reg: # If total reg. are more or equal to max value then close the reg.
print("Registrations are closed!")
return
# Otherwise if registrations are open then increase the value of total reg by 1
# And register the user with unique registration number [reg_no] allotted to him
await db.execute_query('UPDATE Data SET Total_Reg = Total_Reg + 1 WHERE rowid = 1')
reg_no = total + 1
registrations[reg_no] = user
await close_registration()
"""Also, in case of Queue or execution of this function once at a time, I
want this function to continue executing the code and shouldn't wait for
this line of code particularly, i.e await close_registration() should
keep on executing in background without blocking the current execution of
this function. So should I use asyncio.ensure_future(close_registration())
instead of await or what?"""
我希望你知道我在这里要做什么。现在,让我们来谈谈我的疑问。一旦有人输入apply
命令,apply
功能就会被discord触发,因此可能存在data = await db.execute_query('SELECT Total_Reg from Data WHERE rowid = 1')
可以同时执行多次的情况,这将导致返回当时相同数量的注册,并将其存储在所有注册的总变量中。
我知道,当已经有连接更新或访问数据库时,sqlite会锁定数据库,但一旦执行了一个查询,另一个查询就会在执行await db.execute_query('UPDATE Data SET Total_Reg = Total_Reg + 1 WHERE rowid = 1')
增量查询之前开始执行。
我想要的基本上是
这应该是订单:
- 获取
data = await db.execute_query('SELECT Total_Reg from Data WHERE rowid = 1')
的当前注册数 - 检查注册是否已满
- 如果没有,则注册用户并通过
await db.execute_query('UPDATE Data SET Total_Reg = Total_Reg + 1 WHERE rowid = 1')
将当前注册数量增加1来更新数据库
例如,如果两个用户同时申请注册,则其中一个用户应首先注册,然后仅注册另一个用户,并且这两个用户的reg_no
应是唯一的。
就是这样。我该如何实现这个功能?我应该使用队列吗?或者,sqlite中是否有任何功能可以首先获取当前reg,然后在值小于max_reg
的情况下将其增加1,并且仅在一个查询中完成所有这些操作?
谢谢!
可能存在SQL解决方案,但您可以在discord.py 的帮助下继续进行此操作
@commands.max_concurrency(1, commands.BucketType.guild, True)
@commands.command() or #@bot.command() depends on what you are using
async def apply(ctx):
#command here
@commands.max_concurrency(number, bucket_type, wait)
允许您控制命令的并发性number
是它可以同时使用的最大次数bucket_type
是应该检查并发性的地方,guild意味着在单个guild中,如果您希望它是全局的,请使用commands.BucketType.default
wait
是在有人使用该命令而不应该运行该命令时应该执行的操作。如果我们将其设置为true,它将等待命令完成运行,如果wait为false,它将引发一个错误,该错误可以用错误处理程序捕获。
如果你只想同时执行一次函数,
@commands.command(hidden=True)
@commands.max_concurrency(1, commands.BucketType.guild, True)
async def register(ctx, args):
#do stuff
然而,人们将可以使用注册。
@commands.command()
async def apply(args):
ctx.command = bot.get_command('register')
await bot.invoke(ctx)
非常混乱的代码,但应该可以工作。
参考文献:
- 最大货币
- BucketType