如何在并发运行的函数中一次执行一部分代码? [英] How can I execute some part of code once at a time in a concurrently running function?

查看:33
本文介绍了如何在并发运行的函数中一次执行一部分代码?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

因此,让我简要介绍一下您要实现的目标.我有一个名为 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.

我基本上想要的是

这应该是顺序:

  1. 使用获取当前注册数data = await db.execute_query('从Data WHERE rowid = 1'中选择SELECT Total_Reg')
  2. 检查注册是否完整
  3. 如果不是,则注册用户并通过增加当前编号来更新数据库.使用 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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆