如何在并发运行的函数中一次执行一部分代码? [英] How can I execute some part of code once at a time in a concurrently running function?
问题描述
因此,让我简要介绍一下您要实现的目标.我有一个名为 apply
的命令,一旦有人输入该命令,就会开始执行apply函数.现在,apply函数具有一些我想同时执行的代码部分,以防万一许多用户同时触发了该命令,并且有一个异步函数称为 register
,我想执行该函数一次一次.这是代码的简要介绍:
So, let me give you a brief of what am trying to achieve. I've a command called apply
, as soon as some one enters that command, execution of apply function begins. Now, apply function have some part of code which I want to be executed concurrently in case if many users triggered that command at the same time, and there is a async function called register
which I want to be executed once at a time. Here's the glimpse of the code:
@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
命令,就会由discord触发 apply
函数,因此在某些情况下, data = await db.execute_query('SELECT Total_Reg from可以在同一时间多次执行WHERE rowid = 1')
数据,这将导致同时返回相同数量的注册并将其存储在所有注册的总变量中.
I hope you get the idea what am trying to do here. Now, let's come to my query.
apply
function is triggered by discord as soon as some one enters apply
command, so there can be some case that data = await db.execute_query('SELECT Total_Reg from Data WHERE rowid = 1')
can be executed multiple times at the same time which will cause the same number of registrations at that time to be returned and stored in total variable of all of them.
我知道,当已有连接更新或访问数据库时,sqlite会锁定数据库,但是一旦执行查询,另一个将在 await db.execute_query('UPDATE数据SET Total_Reg = Total_Reg + 1 WHERE rowid = 1')
执行增量查询.
I know, sqlite locks the database when there is already a connection updating or accessing the database but then also, as soon as a query is executed, another will start executing there itself before await db.execute_query('UPDATE Data SET Total_Reg = Total_Reg + 1 WHERE rowid = 1')
Increment query is executed.
我基本上想要的是
这应该是顺序:
- 使用
获取当前注册数data = await db.execute_query('从Data WHERE rowid = 1'中选择SELECT Total_Reg')
- 检查注册是否完整
- 如果不是,则注册用户并通过增加当前编号来更新数据库.使用
await db.execute_query('UPDATE Data SET Total_Reg = Total_Reg + 1 WHERE rowid = 1')的注册数
例如,如果有2个用户同时申请注册,则应首先注册一个用户,然后才应该注册另一个用户,并且两个用户的 reg_no
应该是唯一的.
For example, if 2 users applied to register at the same time, then one should be registered first and then only another should get registered and reg_no
for both of them should be unique.
就是这样.如何实现此功能?我应该使用队列吗?还是在sqlite中有任何功能可以首先获取当前的reg.然后如果它小于 max_reg
,并且仅通过一个查询就获得所有这些值,则将值增加1?
So, that's it. How can I achieve this functionality? Should I use a Queue? Or is there any feature in sqlite to first get the current reg. and then increase the value by 1 if it's less than max_reg
and all this in just a single query?
谢谢!
推荐答案
可能存在一个SQL解决方案,但是您可以在discord.py的帮助下进行此操作
Well there possibly exists an SQL solution, but you could proceed with this with the help of 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
是应该检查并发性的位置,如果您希望将其设置为全局,则行会在单个行会中进行.
如果有人使用该命令并且不应运行该命令,则应该执行 wait
.如果将其设置为true,它将等到命令完成运行为止;如果wait为false,将引发错误,该错误可以由错误处理程序捕获.
@commands.max_concurrency(number, bucket_type, wait)
lets you control the concurrency of the command.
number
is the max number of times it can be used concurrently.
bucket_type
is where the concurrency is supposed to be checked, guild means in a single guild, if you want it to be global use commands.BucketType.default
.
wait
is what it should do if someone uses the command and its not supposed to run. if we set it to true it will wait till the command finishes running, if wait is false it will raise an error which can be caught with an error handler.
如果您只希望一个函数同时执行一次,
If you just want a function to be executed once concurrently,
@commands.command(hidden=True)
@commands.max_concurrency(1, commands.BucketType.guild, True)
async def register(ctx, args):
#do stuff
但是人们将能够使用注册.
However people will be able to use register.
@commands.command()
async def apply(args):
ctx.command = bot.get_command('register')
await bot.invoke(ctx)
非常混乱的代码,但应该可以使用.
Very messy code, but should work.
这篇关于如何在并发运行的函数中一次执行一部分代码?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!