Issue 1:
Checklist

I have verified that the issue exists against the master branch of Celery.

This has already been asked to the discussion group first.

I have read the relevant section in the

contribution guide

on reporting bugs.

I have checked the issues list

for similar or identical bug reports.

I have checked the pull requests list

for existing proposed fixes.

I have checked the commit log

to find out if the bug was already fixed in the master branch.

I have included all related issues and possible duplicate issues

in this issue (If there are none, check this box anyway).

Mandatory Debugging Information

I have included the output of celery -A proj report in the issue.

(if you are not able to do this, then at least specify the Celery

version affected).

I have verified that the issue exists against the master branch of Celery.

I have included the contents of pip freeze in the issue.

I have included all the versions of all the external dependencies required

to reproduce this bug.

Optional Debugging Information

I have tried reproducing the issue on more than one Python version

and/or implementation.

I have tried reproducing the issue on more than one message broker and/or

result backend.

I have tried reproducing the issue on more than one version of the message

broker and/or result backend.

I have tried reproducing the issue on more than one operating system.

I have tried reproducing the issue on more than one workers pool.

I have tried reproducing the issue with autoscaling, retries,

ETA/Countdown & rate limits disabled.

I have tried reproducing the issue after downgrading

and/or upgrading Celery and its dependencies.

Related Issues and Possible Duplicates

Related Issues

None

Possible Duplicates

None

Environment & Settings

Celery version: 4.2.2 (windowlicker)

celery report Output:

BROKER_URL: 'redis://127.0.0.1:6379/2'
CELERYBEAT_SCHEDULE: {
}
CELERY_ACCEPT_CONTENT: ['json']
CELERY_ENABLE_UTC: True
CELERY_QUEUES:
( -> celery>,
-> campaigns>)
CELERY_RESULT_SERIALIZER: 'json'
CELERY_ROUTES:
('campaigns.task_routers.CampaignRouter',)
CELERY_TASK_SERIALIZER: 'json'

Steps to Reproduce

Required Dependencies

Minimal Python Version: 3.7

Minimal Celery Version: 4.2.2 vs. 3.1.23

Minimal Kombu Version: 4.3.0 vs. 3.0.35

Minimal Broker Version: N/A or Unknown

Minimal Result Backend Version: N/A or Unknown

Minimal OS and/or Kernel Version: N/A or Unknown

Minimal Broker Client Version: N/A or Unknown

Minimal Result Backend Client Version: N/A or Unknown

Python Packages

pip freeze Output:

amqp==2.5.2
billiard==3.5.0.5
celery==4.2.2
Django==1.8.19
kombu==4.3.0

Other Dependencies

N/A

Minimally Reproducible Test Case

Create a minimum Django app that supports celery on python 3.7 (I've used Django==1.8.19)

Create a task_router for example: CampaignRouter that returns a dictionary:

class CampaignRouter(object):
def route_for_task(self, task, args=None, kwargs=None):
if task.startswith('campaigns.tasks.'):
return {
'queue': 'campaigns',
'routing_key': 'campaigns',
'time_limit': 30, # 30sec <<--- this is the problem
}
return None

Create a task that does stuff for more then 5sec (you are going to pass --time-limit=5 in the command line) for example a 600sec sleep and will be routed by your route:

@app.task(bind=True)
def my_task(self):
time.sleep(1000 * 10) # 10sec
return 1+1

Run your django app

Run celery with the --time-limit=5:

celery worker -B -A sample_proj --loglevel=DEBUG --time-limit 5

execute the task

check if task run into a TimeLimitExceeded error after 5sec and cry:

raise TimeLimitExceeded(job._timeout)
billiard.exceptions.TimeLimitExceeded: TimeLimitExceeded(5,)
[2020-04-02 09:37:05,183: ERROR/MainProcess] Hard time limit (5.0s) exceeded for

Expected Behavior

A task ran through the route should have the "time_limit" from the route's dictionary (30sec).

Actual Behavior

I've included it in the TestCase scenario. The actual behevior is that the task ends after 5sec (the time passed in the command line).

So basically I see that the interface for creating a message in celery.app.base.send_task has changed between 3.1.23 and 4.2.2. In Celery 3.1.23 you were able to pass the 'time_limit' through your route so each task that runs through it will have that specific time_limit (hard time limit in this case). That was done thanks to the **options argument.

Celery 3.1.23 code (celery.app.base.send_task from line 345):

options = router.route(options, name, args, kwargs)
if connection:
producer = self.amqp.TaskProducer(connection)
with self.producer_or_acquire(producer) as P:
self.backend.on_task_call(P, task_id)
task_id = P.publish_task(
name, args, kwargs, countdown=countdown, eta=eta,
task_id=task_id, expires=expires,
callbacks=maybe_list(link), errbacks=maybe_list(link_error),
reply_to=reply_to or self.oid, **options
)

But in Celery 4 this isn't possible because the time_limit is pass from the send_task arguments to the amqp.create_task_message() and the "time_limit" from the route isn't even considered.

Celery 4.2.2 code (celery.app.base.send_task from line 716):

options = router.route(
options, route_name or name, args, kwargs, task_type)

if not root_id or not parent_id:
parent = self.current_worker_task
if parent:
if not root_id:
root_id = parent.request.root_id or parent.request.id
if not parent_id:
parent_id = parent.request.id

message = amqp.create_task_message(
task_id, name, args, kwargs, countdown, eta, group_id,
expires, retries, chord,
maybe_list(link), maybe_list(link_error),
reply_to or self.oid, time_limit, soft_time_limit,
self.conf.task_send_sent_event,
root_id, parent_id, shadow, chain,
argsrepr=options.get('argsrepr'),
kwargsrepr=options.get('kwargsrepr'),
)

This is in my opinion a big (not huge) regression because let's see this scenario of a existing project:

10 django apps

each app has 10tasks

your 'slow app' has 20tasks

If the project used celery 3.1.23 it just needed to create a route and set a key in the returned dictionary to like this: {(other_keys), 'time_limit': 1000}. But if the project decides to use the newest celery it need to add time_limit parameter to each task decorator for the slow app which will end up changing 20 places instead of handling this through the route. And what if we consider to add a new queue that will be for 'medium apps' that should have a smaller time_limit the the queue used be our 'slow app' but a bigger one the the default queue? We need to to the same job - upgrade each decorator with a specific time_limit.

This sums up to that each task can have it's own time_limit OR the global time_limit. There is no 'golden mean' which was provided in 3.1.23 thanks to routes.

How can this be fixed?

My suggestion is to consider the time_limits params from a route. To get this done the keywords can even have the same names as the celery_configs (for convention) like: task_time_limit / task_soft_time_limit

Issue 2:
Checklist

I have checked the issues list

for similar or identical bug reports.

I have checked the pull requests list

for existing proposed fixes.

I have checked the commit log

to find out if the bug was already fixed in the master branch.

I have included all related issues and possible duplicate issues in this issue

(If there are none, check this box anyway).

Related Issues and Possible Duplicates

Related Issues

None

Possible Duplicates

None

Description

When starting workers like some examples in the documentation that uses lowercase info as argument to loglevel I get this error: Error: Invalid value for '-l' / '--loglevel': invalid choice: info. (choose from DEBUG, INFO, WARNING, ERROR, CRITICAL, FATAL). I assume this is because of the change to Click in 5.0.

Suggestions

Review documentation for instances of lowercase loglevel being passed and update them to use uppercase.