<h1 dir="auto">Checklist</h1>
<ul class="contains-task-list">
<li class="task-list-item"><input type="checkbox" id="" disabled="" class="task-list-item-checkbox" checked=""> I have checked the <a href="https://github.com/celery/celery/issues?q=is%3Aissue+label%3A%22Issue+Type%3A+Enhancement%22+-label%3A%22Category%3A+Documentation%22">issues list</a><br>
for similar or identical enhancement to an existing feature.</li>
<li class="task-list-item"><input type="checkbox" id="" disabled="" class="task-list-item-checkbox" checked=""> I have checked the <a href="https://github.com/celery/celery/pulls?q=is%3Apr+label%3A%22Issue+Type%3A+Enhancement%22+-label%3A%22Category%3A+Documentation%22">pull requests list</a><br>
for existing proposed enhancements.</li>
<li class="task-list-item"><input type="checkbox" id="" disabled="" class="task-list-item-checkbox" checked=""> I have checked the <a href="https://github.com/celery/celery/commits/master">commit log</a><br>
to find out if the if the same enhancement was already implemented in the<br>
master branch.</li>
<li class="task-list-item"><input type="checkbox" id="" disabled="" class="task-list-item-checkbox" checked=""> I have included all related issues and possible duplicate issues in this issue<br>
(If there are none, check this box anyway).</li>
</ul>
<h1 dir="auto">Brief Summary</h1>
<p dir="auto">I think it would be more convenient to build the documentation using a docker service instead of installing locally the tex* libs. With that the documentation contributors could quickly inspect, build and contribute to the documentation.</p>
<h2 dir="auto">Proposed Behavior</h2>
<p dir="auto">It can use the <code class="notranslate">sphinx-autobuild</code> lib to build and serve on port <code class="notranslate">:7000</code>. It won't affect any existing features as far as I am familiar.</p>
<h2 dir="auto">Proposed UI/UX</h2>
<p dir="auto">It can be simply like that:</p>
<div class="highlight highlight-text-shell-session notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="$ docker-compose -f docker/docker-compose.yml run --rm docs make livehtml` "><pre class="notranslate">$ <span class="pl-s1">docker-compose -f docker/docker-compose.yml run --rm docs make livehtml<span class="pl-s"><span class="pl-pds">`</span> </span></span></pre></div>
<p dir="auto">Or it can simply be build &amp; run with an entry point.</p>
<div class="highlight highlight-text-shell-session notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="$ docker-compose -f docker/docker-compose.yml up --build docs"><pre class="notranslate">$ <span class="pl-s1">docker-compose -f docker/docker-compose.yml up --build docs</span></pre></div>
<p dir="auto">I've created the service as PoC: <a href="https://github.com/syrull/celery/commit/60ae8f1922977c858e9d09ffc6fc6f3dad1c3186">https://github.com/syrull/celery/commit/60ae8f1922977c858e9d09ffc6fc6f3dad1c3186</a></p>
<h1 dir="auto">Checklist</h1>

<ul class="contains-task-list">
<li class="task-list-item"><input type="checkbox" id="" disabled="" class="task-list-item-checkbox"> I have checked the <a href="https://github.com/celery/celery/issues?utf8=%E2%9C%93&amp;q=is%3Aissue+label%3A%22Issue+Type%3A+Feature+Request%22+">issues list</a><br>
for similar or identical feature requests.</li>
<li class="task-list-item"><input type="checkbox" id="" disabled="" class="task-list-item-checkbox"> I have checked the <a href="https://github.com/celery/celery/pulls?utf8=%E2%9C%93&amp;q=is%3Apr+label%3A%22PR+Type%3A+Feature%22+">pull requests list</a><br>
for existing proposed implementations of this feature.</li>
<li class="task-list-item"><input type="checkbox" id="" disabled="" class="task-list-item-checkbox"> I have checked the <a href="https://github.com/celery/celery/commits/master">commit log</a><br>
to find out if the if the same feature was already implemented in the<br>
master branch.</li>
<li class="task-list-item"><input type="checkbox" id="" disabled="" class="task-list-item-checkbox"> I have included all related issues and possible duplicate issues<br>
in this issue (If there are none, check this box anyway).</li>
</ul>
<h2 dir="auto">Related Issues and Possible Duplicates</h2>

<h4 dir="auto">Related Issues</h4>
<ul dir="auto">
<li>None</li>
</ul>
<h4 dir="auto">Possible Duplicates</h4>
<ul dir="auto">
<li>None</li>
</ul>
<h1 dir="auto">Brief Summary</h1>

<h1 dir="auto">Design</h1>
<p dir="auto">A. Implementation</p>
<blockquote>
</blockquote>
<div class="snippet-clipboard-content notranslate position-relative overflow-auto" data-snippet-clipboard-copy-content="class BeatCallBacl(object):
    def __init__(self, func, *args, **kwargs):
        self._func = func
        self._func_params = {
            &quot;args&quot;: args,
            &quot;kwargs&quot;: kwargs
        }

    def __call__(self):
        ret = self._func(*self._func_params[&quot;args&quot;], **self._func_params[&quot;kwargs&quot;])
        LOG.info(&quot;beat call: {}, ret:{}&quot;.format(self._func.__name__, ret))
        return ret


class Scheduler(object):
	def apply_async(self, entry, producer=None, advance=True, **kwargs):
    	# Update time-stamps and run counts before we actually execute,
    	# so we have that done if an exception is raised (doesn't schedule
    	# forever.)
        entry = self.reserve(entry) if advance else entry
        task = self.app.tasks.get(entry.task)

        try:
            entry_args = [v() if isinstance(v, BeatCallBacl) else v for v in entry.args]
            entry_kwargs = {k: v() if isinstance(v, BeatCallBacl) else v for k, v in entry.kwargs.items()}
            LOG.info(entry_args)
            LOG.info(entry_kwargs)
            if task:
                return task.apply_async(entry_args, entry_kwargs,
                                        producer=producer,
                                        **entry.options)
            else:
                return self.send_task(entry.task, entry_args, entry_kwargs,
                                      producer=producer,
                                      **entry.options)
        except Exception as exc:  # pylint: disable=broad-except
            reraise(SchedulingError, SchedulingError(
                &quot;Couldn't apply scheduled task {0.name}: {exc}&quot;.format(
                    entry, exc=exc)), sys.exc_info()[2])
        finally:
            self._tasks_since_sync += 1
            if self.should_sync():
                self._do_sync()"><pre class="notranslate"><code class="notranslate">class BeatCallBacl(object):
    def __init__(self, func, *args, **kwargs):
        self._func = func
        self._func_params = {
            "args": args,
            "kwargs": kwargs
        }

    def __call__(self):
        ret = self._func(*self._func_params["args"], **self._func_params["kwargs"])
        LOG.info("beat call: {}, ret:{}".format(self._func.__name__, ret))
        return ret


class Scheduler(object):
	def apply_async(self, entry, producer=None, advance=True, **kwargs):
    	# Update time-stamps and run counts before we actually execute,
    	# so we have that done if an exception is raised (doesn't schedule
    	# forever.)
        entry = self.reserve(entry) if advance else entry
        task = self.app.tasks.get(entry.task)

        try:
            entry_args = [v() if isinstance(v, BeatCallBacl) else v for v in entry.args]
            entry_kwargs = {k: v() if isinstance(v, BeatCallBacl) else v for k, v in entry.kwargs.items()}
            LOG.info(entry_args)
            LOG.info(entry_kwargs)
            if task:
                return task.apply_async(entry_args, entry_kwargs,
                                        producer=producer,
                                        **entry.options)
            else:
                return self.send_task(entry.task, entry_args, entry_kwargs,
                                      producer=producer,
                                      **entry.options)
        except Exception as exc:  # pylint: disable=broad-except
            reraise(SchedulingError, SchedulingError(
                "Couldn't apply scheduled task {0.name}: {exc}".format(
                    entry, exc=exc)), sys.exc_info()[2])
        finally:
            self._tasks_since_sync += 1
            if self.should_sync():
                self._do_sync()
</code></pre></div>
<p dir="auto">B. Instructions</p>
<blockquote>
</blockquote>
<div class="snippet-clipboard-content notranslate position-relative overflow-auto" data-snippet-clipboard-copy-content="beat_schedule = {
    'gen_course_records-every-5-minutes': {
        'task': 'test',
        'schedule': 300,
        'kwargs': {
            &quot;current&quot;: BeatCallBack(datetime.datetime.now)
        }
    }
}"><pre class="notranslate"><code class="notranslate">beat_schedule = {
    'gen_course_records-every-5-minutes': {
        'task': 'test',
        'schedule': 300,
        'kwargs': {
            "current": BeatCallBack(datetime.datetime.now)
        }
    }
}
</code></pre></div>
<h2 dir="auto">Architectural Considerations</h2>

<p dir="auto">None</p>
<h2 dir="auto">Proposed Behavior</h2>

<h2 dir="auto">Proposed UI/UX</h2>

<h2 dir="auto">Diagrams</h2>

<p dir="auto">N/A</p>
<h2 dir="auto">Alternatives</h2>

<p dir="auto">None</p>