-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathslides_jobs_and_tasks.html
More file actions
381 lines (358 loc) Β· 26.1 KB
/
slides_jobs_and_tasks.html
File metadata and controls
381 lines (358 loc) Β· 26.1 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Slides for
Jobs and Tasks in Rails β Ruby on Rails Guides
</title>
<link rel="stylesheet" type="text/css" href="stylesheets/style.css" data-turbo-track="reload">
<link rel="stylesheet" type="text/css" href="stylesheets/print.css" media="print">
<link rel="stylesheet" type="text/css" href="stylesheets/highlight.css" data-turbo-track="reload">
<meta name="apple-mobile-web-app-capable" content="yes">
<meta name="apple-mobile-web-app-status-bar-style" content="black-translucent">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" href="stylesheets/reset.css">
<link rel="stylesheet" href="stylesheets/reveal.css">
<link rel="stylesheet" href="stylesheets/myslide.css" id="theme">
<link rel="stylesheet" href="stylesheets/code.css">
<script src="javascripts/clipboard.js" data-turbo-track="reload"></script>
<script src="javascripts/slides.js" data-turbo-track="reload"></script>
</head>
<body>
<div class="reveal">
<!-- Any section element inside of this container is displayed as a slide -->
<div class="slides">
<section>
<h1>Jobs and Tasks in Rails</h1><p>Your web application will need code that
is run outside the HTTP Request-Response cycle.</p><p>By referring to this guide, you will be able to:</p>
<ul>
<li>Implement tasks that you can start from the commandline</li>
<li>Implement jobs that are run automatically, but asyncronously</li>
</ul>
<p><small>Slides - use arrow keys to navigate, esc to return to page view, f for fullscreen</small></p>
</section>
<section><a class='slide_break' href='jobs_and_tasks.html#slide-0'>β»</a>
<h2 id="http-request-response-cycle"><a class="anchorlink" href="#http-request-response-cycle"><span>1</span> HTTP Request-Response Cycle</a></h2><p>A backend web frameworks normally works within the HTTP Request-Response Cyle.
In a Ruby on Rails app the flow is like this:</p>
<ol>
<li>a HTTP Request comes in</li>
<li>the router deciphers the URL, decides which controller to call</li>
<li>the controller handles HTTP Parameters, Cookies, Session Data,
<ol>
<li>loads models from the database</li>
<li>decides which view to call</li>
<li>sets headers for the HTTP response</li>
<li>renders the view</li>
</ol></li>
<li>a HTTP Response is sent</li>
</ol>
<p>This should take less than 500ms from start to finish if
we want to achive a good response time for our users.</p></section>
<section><a class='slide_break' href='jobs_and_tasks.html#slide-1'>β»</a>
<p>But some code we write is different:
it might not fit within this
timeframe. or it might not be triggered by a HTTP request.</p><p>Some examples:</p>
<ul>
<li>convert uploaded media (images, movies) to different file formats or sizes</li>
<li>send out e-mails</li>
<li>delete data according to GDPR</li>
<li>batch import data to your app</li>
</ul>
</section>
<section><a class='slide_break' href='jobs_and_tasks.html#slide-2'>β»</a>
<h2 id="tasks"><a class="anchorlink" href="#tasks"><span>2</span> Tasks</a></h2></section>
<section><a class='slide_break' href='jobs_and_tasks.html#slide-3'>β»</a>
<h3 id="what-is-a-task-questionmark"><a class="anchorlink" href="#what-is-a-task-questionmark"><span>2.1</span> What is a task?</a></h3><p>In a Rails App <strong>tasks</strong> are small programs you - as the developer - can start on the command line.</p><p>You have already used some predefined tasks:</p><div class="interstitial code">
<pre><code class="highlight shell"><span class="nv">$ </span><span class="nb">rails </span>db:migrate
<span class="nv">$ </span><span class="nb">rails test</span>
</code></pre>
<button class="clipboard-button" data-clipboard-text="$ rails db:migrate
$ rails test
">Copy</button>
</div>
<p>You can get a list of all available tasks with <code>rails -T</code>.</p><p>When you deploy your app to a PAAS like heroku or dokku you can
start a task on the server using the command line:</p><div class="interstitial code">
<pre><code class="highlight shell"><span class="nv">$ </span>dokku run <span class="nb">rails </span>db:migrate
<span class="nv">$ </span>heroku run <span class="nb">rails </span>db:migrate
</code></pre>
<button class="clipboard-button" data-clipboard-text="$ dokku run rails db:migrate
$ heroku run rails db:migrate
">Copy</button>
</div>
<p>A task can have access to your application models, perform database queries, and so on.</p></section>
<section><a class='slide_break' href='jobs_and_tasks.html#slide-4'>β»</a>
<h3 id="how-do-i-generate-a-task-questionmark"><a class="anchorlink" href="#how-do-i-generate-a-task-questionmark"><span>2.2</span> How do I generate a task?</a></h3><p>Use <code>rails generate</code> to start writing a task. For example I want to write
a task that loads user data from ActiveDirectory:</p><div class="interstitial code">
<pre><code class="highlight ruby"><span class="err">$</span> <span class="n">rails</span> <span class="n">generate</span> <span class="n">task</span> <span class="n">active_directory</span> <span class="nb">load</span>
<span class="n">create</span> <span class="n">lib</span><span class="o">/</span><span class="n">tasks</span><span class="o">/</span><span class="n">active_directory</span><span class="p">.</span><span class="nf">rake</span>
</code></pre>
<button class="clipboard-button" data-clipboard-text="$ rails generate task active_directory load
create lib/tasks/active_directory.rake
">Copy</button>
</div>
<p>This will create a file <code>lib/tasks/active_directory.rake</code></p><div class="interstitial code">
<pre><code class="highlight ruby"><span class="n">namespace</span> <span class="ss">:active_directory</span> <span class="k">do</span>
<span class="n">desc</span> <span class="s2">"add your description here"</span>
<span class="n">task</span> <span class="ss">load: :environment</span> <span class="k">do</span>
<span class="c1"># add your code here</span>
<span class="k">end</span>
<span class="k">end</span>
</code></pre>
<button class="clipboard-button" data-clipboard-text="namespace :active_directory do
desc "add your description here"
task load: :environment do
# add your code here
end
end
">Copy</button>
</div>
<p>This task can be started by running <code>rails active_directory:load</code>.
Notice how the namespace defined in the first line and the taskname defined in the
third line are combined when you call the task on the commandline.</p><p>The description defined with <code>desc</code> is displayed when you run <code>rails -T</code>.</p></section>
<section><a class='slide_break' href='jobs_and_tasks.html#slide-5'>β»</a>
<h3 id="how-can-i-supply-command-line-arguments-questionmark"><a class="anchorlink" href="#how-can-i-supply-command-line-arguments-questionmark"><span>2.3</span> How can I supply command line arguments?</a></h3><p>The task to load data from ActiveDirectory needs arguments.</p><p>The Syntax for arguments is a bit strange: the
arguments need to be supplied in square brackets after the taskname without any spaces:</p><div class="interstitial code">
<pre><code class="highlight shell"><span class="nv">$ </span><span class="nb">rails </span>active_directory:load[username]
<span class="nv">$ </span><span class="nb">rails </span>active_directory:load[username1,username2,username3]
</code></pre>
<button class="clipboard-button" data-clipboard-text="$ rails active_directory:load[username]
$ rails active_directory:load[username1,username2,username3]
">Copy</button>
</div>
</section>
<section><a class='slide_break' href='jobs_and_tasks.html#slide-6'>β»</a>
<p>You can give the arguments names and handle them as a hash, an array,
or as separate values.</p><div class="interstitial code">
<pre><code class="highlight ruby"> <span class="n">task</span> <span class="ss">:load</span><span class="p">,</span> <span class="p">[</span><span class="ss">:a</span><span class="p">,</span> <span class="ss">:b</span><span class="p">,</span> <span class="ss">:c</span><span class="p">]</span> <span class="o">=></span> <span class="ss">:environment</span> <span class="k">do</span> <span class="o">|</span><span class="n">task</span><span class="p">,</span> <span class="n">args</span><span class="o">|</span>
<span class="nb">puts</span> <span class="s2">"arguments as a hash: </span><span class="si">#{</span><span class="n">args</span><span class="p">.</span><span class="nf">to_h</span><span class="si">}</span><span class="s2">"</span>
<span class="nb">puts</span> <span class="s2">"arguments as an array: </span><span class="si">#{</span><span class="n">args</span><span class="p">.</span><span class="nf">to_a</span><span class="si">}</span><span class="s2">"</span>
<span class="nb">puts</span> <span class="s2">"arguments by position: </span><span class="si">#{</span><span class="n">args</span><span class="p">.</span><span class="nf">a</span><span class="si">}</span><span class="s2"> and </span><span class="si">#{</span><span class="n">args</span><span class="p">.</span><span class="nf">b</span><span class="si">}</span><span class="s2"> and </span><span class="si">#{</span><span class="n">args</span><span class="p">.</span><span class="nf">c</span><span class="si">}</span><span class="s2">"</span>
<span class="k">end</span>
</code></pre>
<button class="clipboard-button" data-clipboard-text=" task :load, [:a, :b, :c] => :environment do |task, args|
puts "arguments as a hash: #{args.to_h}"
puts "arguments as an array: #{args.to_a}"
puts "arguments by position: #{args.a} and #{args.b} and #{args.c}"
end
">Copy</button>
</div>
<p>The code above can be run like so:</p><div class="interstitial code">
<pre><code class="highlight shell"><span class="nv">$ </span><span class="nb">rails </span>active_directory:load[1,2,3]
arguments as a <span class="nb">hash</span>: <span class="o">{</span>:a<span class="o">=></span><span class="s2">"1"</span>, :b<span class="o">=></span><span class="s2">"2"</span>, :c<span class="o">=></span><span class="s2">"3"</span><span class="o">}</span>
arguments as an array: <span class="o">[</span><span class="s2">"1"</span>, <span class="s2">"2"</span>, <span class="s2">"3"</span><span class="o">]</span>
arguments by position: 1 and 2 and 3
</code></pre>
<button class="clipboard-button" data-clipboard-text="$ rails active_directory:load[1,2,3]
arguments as a hash: {:a=>"1", :b=>"2", :c=>"3"}
arguments as an array: ["1", "2", "3"]
arguments by position: 1 and 2 and 3
">Copy</button>
</div>
</section>
<section><a class='slide_break' href='jobs_and_tasks.html#slide-7'>β»</a>
<h3 id="how-do-i-implement-my-task-questionmark"><a class="anchorlink" href="#how-do-i-implement-my-task-questionmark"><span>2.4</span> How do I implement my task?</a></h3><p>You can use all your knowledge of ruby, and all the code in your web
application. To finish the taks we can use an already existing
<code>User</code> model and a <code>ActiveDirectoryLookup</code> service object.</p><div class="interstitial code">
<pre><code class="highlight ruby"> <span class="n">task</span> <span class="ss">:load</span><span class="p">,</span> <span class="p">[</span><span class="ss">:username</span><span class="p">]</span> <span class="o">=></span> <span class="ss">:environment</span> <span class="k">do</span> <span class="o">|</span><span class="n">task</span><span class="p">,</span> <span class="n">args</span><span class="o">|</span>
<span class="n">ad</span> <span class="o">=</span> <span class="no">ActiveDirectoryLookup</span><span class="p">.</span><span class="nf">new</span>
<span class="n">args</span><span class="p">.</span><span class="nf">to_a</span><span class="p">.</span><span class="nf">each</span> <span class="k">do</span> <span class="o">|</span><span class="n">username</span><span class="o">|</span>
<span class="n">result</span> <span class="o">=</span> <span class="n">ad</span><span class="p">.</span><span class="nf">query</span><span class="p">(</span><span class="n">username</span><span class="p">)</span>
<span class="k">if</span> <span class="n">result</span><span class="p">.</span><span class="nf">nil?</span>
<span class="nb">puts</span> <span class="s2">"Could not find user </span><span class="si">#{</span><span class="n">username</span><span class="si">}</span><span class="s2"> in ActiveDiretory"</span>
<span class="k">else</span>
<span class="n">u</span> <span class="o">=</span> <span class="no">User</span><span class="p">.</span><span class="nf">find_or_create_with_ldap</span><span class="p">(</span><span class="n">result</span><span class="p">)</span>
<span class="nb">puts</span> <span class="s2">"user </span><span class="si">#{</span><span class="n">username</span><span class="si">}</span><span class="s2"> is local user </span><span class="si">#{</span><span class="n">u</span><span class="si">}</span><span class="s2">"</span>
<span class="k">end</span>
<span class="k">end</span>
<span class="k">end</span>
</code></pre>
<button class="clipboard-button" data-clipboard-text=" task :load, [:username] => :environment do |task, args|
ad = ActiveDirectoryLookup.new
args.to_a.each do |username|
result = ad.query(username)
if result.nil?
puts "Could not find user #{username} in ActiveDiretory"
else
u = User.find_or_create_with_ldap(result)
puts "user #{username} is local user #{u}"
end
end
end
">Copy</button>
</div>
</section>
<section><a class='slide_break' href='jobs_and_tasks.html#slide-8'>β»</a>
<h3 id="scheduling-tasks-on-unix"><a class="anchorlink" href="#scheduling-tasks-on-unix"><span>2.5</span> Scheduling Tasks on UNIX</a></h3><p>On <strong>UNIX</strong> Systems you can use <code>cron</code> to schedule tasks.</p><p>Use <code>crontab -e</code> to edit the cron table. It is a plain text.
The first 5 entries in the table specify the time:</p><div class="interstitial code">
<pre><code class="highlight plaintext"># ββββββββββββββ minute (0 - 59)
# β ββββββββββββββ hour (0 - 23)
# β β ββββββββββββββ day of the month (1 - 31)
# β β β ββββββββββββββ month (1 - 12)
# β β β β ββββββββββββββ day of the week (0 - 6) (Sunday to Saturday;
# β β β β β 7 is also Sunday on some systems)
# β β β β β
# β β β β β
# * * * * * <command to execute>
</code></pre>
<button class="clipboard-button" data-clipboard-text="# ββββββββββββββ minute (0 - 59)
# β ββββββββββββββ hour (0 - 23)
# β β ββββββββββββββ day of the month (1 - 31)
# β β β ββββββββββββββ month (1 - 12)
# β β β β ββββββββββββββ day of the week (0 - 6) (Sunday to Saturday;
# β β β β β 7 is also Sunday on some systems)
# β β β β β
# β β β β β
# * * * * * <command to execute>
">Copy</button>
</div>
<p>In the following example the backup script is run at 10 past midnight
every day:</p><div class="interstitial code">
<pre><code class="highlight plaintext">10 0 * * * /usr/local/bin/backup_script
</code></pre>
<button class="clipboard-button" data-clipboard-text="10 0 * * * /usr/local/bin/backup_script
">Copy</button>
</div>
</section>
<section><a class='slide_break' href='jobs_and_tasks.html#slide-9'>β»</a>
<h3 id="other-task-runners"><a class="anchorlink" href="#other-task-runners"><span>2.6</span> Other Task Runners</a></h3><p>You can use <strong>npm</strong> as a task runner.
Edit <code>package.json</code> and add your tasks under the key <code>scripts</code>:</p><div class="interstitial code">
<pre><code class="highlight json"><span class="p">{</span><span class="w">
</span><span class="nl">"scripts"</span><span class="p">:</span><span class="w"> </span><span class="p">{</span><span class="w">
</span><span class="nl">"compress"</span><span class="p">:</span><span class="w"> </span><span class="s2">"zip -r src.zip src/"</span><span class="p">,</span><span class="w">
</span><span class="p">}</span><span class="w">
</span><span class="p">}</span><span class="w">
</span></code></pre>
<button class="clipboard-button" data-clipboard-text="{
"scripts": {
"compress": "zip -r src.zip src/",
}
}
">Copy</button>
</div>
<p>run the task through <code>npm run compress</code>. This works very well for starting command line scripts
like build or cleanup steps, or running tests.</p><p>See <a href="https://docs.npmjs.com/cli/v6/using-npm/scripts">the npm documentation</a>.</p><p>In <strong>nest.js</strong> <a href="https://docs.nestjs.com/techniques/task-scheduling">task scheduling</a> is handled by node-cron.</p><p>In <strong>Laravel</strong> see <a href="https://laravel.com/docs/9.x/envoy">envoy</a>.</p></section>
<section><a class='slide_break' href='jobs_and_tasks.html#slide-10'>β»</a>
<h2 id="jobs"><a class="anchorlink" href="#jobs"><span>3</span> Jobs</a></h2></section>
<section><a class='slide_break' href='jobs_and_tasks.html#slide-11'>β»</a>
<h3 id="what-is-a-job-questionmark"><a class="anchorlink" href="#what-is-a-job-questionmark"><span>3.1</span> What is a job?</a></h3><p>In a Rails App <strong>jobs</strong> are parts of your app that are not run within the
HTTP Request-Response cycle. They are also called <strong>background jobs</strong>.</p></section>
<section><a class='slide_break' href='jobs_and_tasks.html#slide-12'>β»</a>
<h3 id="how-do-i-generate-a-job-questionmark"><a class="anchorlink" href="#how-do-i-generate-a-job-questionmark"><span>3.2</span> How do I generate a job?</a></h3><p>Use <code>rails generate</code> to get started:</p><div class="interstitial code">
<pre><code class="highlight shell"><span class="nv">$ </span><span class="nb">rails </span>generate job guests_cleanup
invoke test_unit
create <span class="nb">test</span>/jobs/guests_cleanup_job_test.rb
create app/jobs/guests_cleanup_job.rb
</code></pre>
<button class="clipboard-button" data-clipboard-text="$ rails generate job guests_cleanup
invoke test_unit
create test/jobs/guests_cleanup_job_test.rb
create app/jobs/guests_cleanup_job.rb
">Copy</button>
</div>
<p>As you can see a test is generated alongside the job itself.</p><p>Here's what a job looks like:</p><div class="interstitial code">
<pre><code class="highlight ruby"><span class="k">class</span> <span class="nc">GuestsCleanupJob</span> <span class="o"><</span> <span class="no">ApplicationJob</span>
<span class="n">queue_as</span> <span class="ss">:default</span>
<span class="k">def</span> <span class="nf">perform</span><span class="p">(</span><span class="o">*</span><span class="n">args</span><span class="p">)</span>
<span class="c1"># Do something later</span>
<span class="k">end</span>
<span class="k">end</span>
</code></pre>
<button class="clipboard-button" data-clipboard-text="class GuestsCleanupJob < ApplicationJob
queue_as :default
def perform(*args)
# Do something later
end
end
">Copy</button>
</div>
</section>
<section><a class='slide_break' href='jobs_and_tasks.html#slide-13'>β»</a>
<h3 id="how-can-i-start-a-job-later-questionmark"><a class="anchorlink" href="#how-can-i-start-a-job-later-questionmark"><span>3.3</span> How can I start a job - later?</a></h3><p>Somwehere in your rails app, for example in a controller, you can set the job up like this:</p><div class="interstitial code">
<pre><code class="highlight ruby"><span class="no">GuestsCleanupJob</span><span class="p">.</span><span class="nf">perform_later</span><span class="p">(</span><span class="n">guest</span><span class="p">)</span>
</code></pre>
<button class="clipboard-button" data-clipboard-text="GuestsCleanupJob.perform_later(guest)
">Copy</button>
</div>
<p>The job will be peformed asynchronously - outside the HTTP Request-Response cycle.
Calling <code>perform_later</code> will take up almost no time.</p><p>You can also define a time when the job should be run:</p><div class="interstitial code">
<pre><code class="highlight ruby"><span class="no">GuestsCleanupJob</span><span class="p">.</span><span class="nf">set</span><span class="p">(</span><span class="ss">wait_until: </span><span class="no">Date</span><span class="p">.</span><span class="nf">tomorrow</span><span class="p">.</span><span class="nf">noon</span><span class="p">).</span><span class="nf">perform_later</span><span class="p">(</span><span class="n">guest</span><span class="p">)</span>
<span class="no">GuestsCleanupJob</span><span class="p">.</span><span class="nf">set</span><span class="p">(</span><span class="ss">wait: </span><span class="mi">1</span><span class="p">.</span><span class="nf">week</span><span class="p">).</span><span class="nf">perform_later</span><span class="p">(</span><span class="n">guest</span><span class="p">)</span>
</code></pre>
<button class="clipboard-button" data-clipboard-text="GuestsCleanupJob.set(wait_until: Date.tomorrow.noon).perform_later(guest)
GuestsCleanupJob.set(wait: 1.week).perform_later(guest)
">Copy</button>
</div>
</section>
<section><a class='slide_break' href='jobs_and_tasks.html#slide-14'>β»</a>
<h3 id="how-can-i-supply-arguments-questionmark"><a class="anchorlink" href="#how-can-i-supply-arguments-questionmark"><span>3.4</span> How can I supply arguments?</a></h3><p>You can define the argument list for <code>perform</code> any way you want.
The default is <code>*args</code> which captures all the arguments into an array <code>args</code>.</p><p>When calling <code>perform_later</code> you supply the arguments that will end up in <code>perform</code>.</p><p>You can only use primitive data types (Strings, Integers, Symbols, Date) as arguments for your job, but not Ruby Objects.</p><p>Why? Because the Job is sent to a Queueing System for Storage. The data has to be serialized into a String, and deserialized again when it comes back to Rails.</p><p>The good news is: serialization and deserialization is automatically done for ActiveRecord models.
So you can use models as arguments. But remember to implement de/serialization for any
other objects you want to use.</p></section>
<section><a class='slide_break' href='jobs_and_tasks.html#slide-15'>β»</a>
<h3 id="how-do-i-send-e-mail-later-questionmark"><a class="anchorlink" href="#how-do-i-send-e-mail-later-questionmark"><span>3.5</span> How do I send E-Mail - later?</a></h3><p>When sending E-Mail from Rails you can specify if you want
to do it synchronously or asynchronously:</p><div class="interstitial code">
<pre><code class="highlight ruby"><span class="c1"># If you want to send the email now use #deliver_now</span>
<span class="no">UserMailer</span><span class="p">.</span><span class="nf">welcome</span><span class="p">(</span><span class="vi">@user</span><span class="p">).</span><span class="nf">deliver_now</span>
<span class="c1"># If you want to send the email asynchronously through a Job use #deliver_later</span>
<span class="no">UserMailer</span><span class="p">.</span><span class="nf">welcome</span><span class="p">(</span><span class="vi">@user</span><span class="p">).</span><span class="nf">deliver_later</span>
</code></pre>
<button class="clipboard-button" data-clipboard-text="# If you want to send the email now use #deliver_now
UserMailer.welcome(@user).deliver_now
# If you want to send the email asynchronously through a Job use #deliver_later
UserMailer.welcome(@user).deliver_later
">Copy</button>
</div>
</section>
<section><a class='slide_break' href='jobs_and_tasks.html#slide-16'>β»</a>
<h3 id="how-do-i-configure-a-queuing-backend-questionmark"><a class="anchorlink" href="#how-do-i-configure-a-queuing-backend-questionmark"><span>3.6</span> How do I configure a queuing backend?</a></h3><p>In development you can use the default queuing system called <code>async</code>.
It's a poor fit for production since it drops pending jobs on restart.</p><p>For production you can chose another queuing backend, for example
<a href="https://github.com/bensheldon/good_job#set-up">GoodJob</a> which
uses the Postgres Database to store the jobs.</p></section>
<section><a class='slide_break' href='jobs_and_tasks.html#slide-17'>β»</a>
<h2 id="beyond-tasks-and-jobs"><a class="anchorlink" href="#beyond-tasks-and-jobs"><span>4</span> Beyond Tasks and Jobs</a></h2><p>Using Jobs is a first step towards a more complex software architecture.
We have been building Web Apps from different parts that communicate through
APIs. Both REST APIs and GraphQL APIs are synchronous.</p><p>Jobs and asynchronous work open up a new way of thinking of our application: it
could be built from several parts that send each other messages, but don't wait
for a response.</p></div></section>
</div>
</div>
<!-- End slides. -->
<!-- Required JS files. -->
<script src="javascripts/reveal.js"></script>
<script src="javascripts/search.js"></script>
<script src="javascripts/markdown.js"></script>
<script>
// Also available as an ES module, see:
// https://revealjs.com/initialization/
Reveal.initialize({
controls: false,
progress: true,
center: false,
hash: true,
// The "normal" size of the presentation, aspect ratio will
// be preserved when the presentation is scaled to fit different
// resolutions. Can be specified using percentage units.
width: 1000,
height: 600,
disableLayout: false,
// Factor of the display size that should remain empty around
// the content
margin: 0.05,
// Bounds for smallest/largest possible scale to apply to content
minScale: 0.2,
maxScale: 10.0,
keyboard: {
27: () => {
// do something custom when ESC is pressed
var new_url = window.location.pathname.replace('slides_', '') + window.location.hash.replace('/','slide-');
window.location = new_url;
},
191: 'toggleHelp',
13: 'next', // go to the next slide when the ENTER key is pressed
},
// Learn about plugins: https://revealjs.com/plugins/
plugins: [ RevealSearch, RevealMarkdown ]
});
</script>
</body>
</html>