Package: dj-cloud-task
Django Cloud Task QueueIntegrate yourDjangoapplication with GoogleCloud TaskfromGoogle Cloud Platform. This package provides a simple and easy to use decorator to push tasks to Cloud Task Queue and automatically handle all income task execution requests from Cloud Task. In a single entry point.At the moment dj-cloud-task only works with HTTP targets such as Cloud Run, Cloud Functions, Compute Engine, ... (in case you are using Google Cloud Platform infrastructure). See the Cloud Task documentation about targets for morehere!Some FeaturesEasily push tasks to Cloud Task using a decoratorAutomatically route all tasks from a single endpointEase scheduling with native python datetimeNamed task to avoid duplicatedLocal development support with Redis QueueInstallationSimpledj-cloud-taskcan be installed withpip:pip install dj-cloud-taskOr from this repository:pip install -e git+https://github.com/txiocoder/dj-cloud-task.git@main#egg=cloudtaskRequirementsPython>= 3.9django>= 3.2.*google-cloud-tasks>= 2.5.*These are the officially supported python and packages versions. Other versions will probably workQuickstartConfigureAs stated above, Django Cloud Task is a Django Application. To configure your project you simply need to addcloudtaskto yourINSTALLED_APPSand configure theCLOUDTASKvariable in thesettings.pyfile. More details about how to configure the CLOUDTASK variable below.In filesettings.py:INSTALLED_APPS:list=['cloudtask',]CLOUDTASK:dict={'PROJECT':'project','LOCATION':'europe-west6','SAE':'user@project.iam.gserviceaccount.com','URL':'https://handler.com/_tasks/','QUEUE':'default','SECRET':'my-very-secrete-key'}Then, addcloudtask.urlsto your URL configuration to route and handle all task execution requests coming from Cloud Task.In yourproject.urls:fromdjango.urlsimportpath,includeurlpatterns:list=[path('_tasks/',include('cloudtask.urls'))]Create TasksThe tasks are simple python functions that could be defined anywhere. But, I suggest you create a file with the nametasks.pyin your django module/app and declare there. To create a task, simply decorate a function withcloudtask.decorators.task. See the example below:fromcloudtaskimport(CloudTaskRequest,task)@task(queue='default')defadd(request:CloudTaskRequest,a:int=5,b:int=4)->None:print(f'Running task with args{a=}and{b=}')print(a+b)Run TasksTo send a task to Cloud Task call the task function and then call the delay method inside the returned task instance. This will send a request to Cloud Task to enqueue the task and Cloud Task will request to run it as fast as possible.from.tasksimportaddadd(a=10,b=30).delay()# or use the alias pushadd(a=30,b=10).push()GCP AuthenticationThis module requires to be authenticated with Google Cloud Platform as a service. The GC Platform provides various ways to authenticate with it. See the GC Platform page about authentication strategieshere.ConfigurationsIn this session you will see how to configure cloudtask. We have required attributes, optional but required in task declaration and  only optional attributes.
The required attributes arePROJECT,LOCATIONandSAE.Here the details about all attributes accpeted inCLOUDTASKAttributeTypeRequiredDescriptionPROJECTstrTrueProject ID from Google Cloud PlatformLOCATIONstrTrueCloud Task Queue LocationSAEstrTrueService Account EmailURLstrFalseDefault URLQUEUEsrtFalseDefault Queue NameSECRETstrFalseSecret key to authorize task executionLOCAL_RQboolFalseUse Redis Queue to handle tasks locallyLOCAL_RQ_URLstrFalseOptional Redis connection URLTESTINGboolFalseTesting ModeURL attributeThe URL attribute is optional, but if you don't set you will need to explicitly pass as  a task decorator argumentfromcloudtaskimporttask@task(queue='emails',url='https://mysite.com/emails-tasks')defsend_email(request,to:str):passYou can change theurlof task instance in runtime if you need things to be done more automated.from.tasksimportsend_emailtask=send_email(to='a@a.com')task.url='https://mysite.com/tasks'task.push()QUEUE attributeThe same as the URL attribute, the QUEUE attribute is optional, and if you don't set it you will need to explicitly pass as a task decorator argument. You can not change the QUEUE of task instance at runtime.fromcloudtaskimporttask@task(queue='default')defsend_email(request,to:str):passTESTING attributeUseful when testing your django application. If True will run all tasks immediately without push to Cloud Task QueueWorking with TasksIn this session you will see how to play with tasks. Django Cloud Task provides not just one way to create, push and handle tasks. It's flexible! All defined tasks receive therequestkeyword argument which is an instance ofcloudtask.tasks.CloudTaskRequestcontaining all request information from Cloud TaskCreating and Pushfromcloudtaskimport(CloudTaskRequest,task)@task()defsay_yes(rquest)->None:print('Yes')@task(queue='default',named=True)defadd(request:CloudTaskRequest,a:int=5,b:int=4)->None:print(f'Running task with args{a=}and{b=}')print(a+b)# Pushing to Cloud Tasksay_yes().delay()# or with pushadd().push()Immediately Execute a TaskSometimes you will need to execute the task function immediately (without pushing to Cloud Task), to do that, just call the__cal__orexecutemethod from the returned task instance. The request will have limited information.from.tasksimportaddadd(a=5,b=3).__call__()# or using the aliasadd(a=5,b=3)()# or using the execute methodadd(a=5,b=3).execute()SchedulingYou can schedule a task to be delivered later using native python datetime.fromdatetimeimporttimedeltafromdjango.utils.timezoneimportnowfrom.tasksimportaddat=now()+timedelta(days=2)add(a=3,b=6).schedule(at=at)Named Tasksfrom.tasksimportaddadd(a=3,b=6).delay()add(a=3,b=6).delay()add(a=3,b=6).delay()By default, the above will run normally. Cloud Task by default adds a unique name for each new task. That makes it possible to have duplicated tasks in the queue, even with the same arguments. If you want a task to only be enqueued once at time, you have to set the task as a named task.Django Cloud Task will give a task name based on the task function name.fromcloudtaskimport(CloudTaskRequest,task)@task(named=True)defclean_expired(request:CloudTaskRequest):passclean_expired().delay()clean_expired().delay()# this line will raise an entity error by Cloud TaskYou can also set the name intaskdecorator or dynamically. This feature is very useful when you want to do some recursive tasks.fromcloudtask.tasksimportTaskfromcloudtaskimport(CloudTaskRequest,task)@task(named='SOME_UNIQUE_NAME')deftask_do_some(request:CloudTaskRequest):pass# or dynamically@task()defdelete_article(request:CloudTaskRequest,article_id:int):passarticle_id:int=34task:Task=delete_article(article_id=article_id)task.named=f'DELETE_ARTICLE_{article_id}'task.push()Local development supportSetupUse Redis Queue for local development support. To start, first installrq,rq-schedulerandrequestswith pip. You will need a Redis connection too. Then configure on yourCLOUDTASKsettings.pipinstallrqrequestsrq-schedulerConfigurationsOnCLOUDTASKsettings setLOCAL_RQasTrueto start handle the tasks locally.CLOUDTASK:dict={'LOCAL_RQ':True}You can useLOCAL_RQ_URLto change the default redis connection stringCLOUDTASK:dict={'LOCAL_RQ':True,'LOCAL_RQ_URL':'redis://localhost:6379'# default by redis}That is all, but do not forget to set the right localURLon yourCLOUDTASKsettings to  handle the tasks.Running Tasks LocallyTo start running task locally just start the worker process with the available management commandpythonmanage.pycloudtask-workerIf you have task that are scheduled, start therqschedulerworker process to support scheduling tasks. In your project root dir:rqscheduler