passive_queue 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,623 @@
1
+ # ================================
2
+ # lib/passive_queue/web.rb
3
+ # ================================
4
+ require 'erb'
5
+ require 'json'
6
+
7
+ module PassiveQueue
8
+ class Web
9
+ def call(env)
10
+ request = Rack::Request.new(env)
11
+
12
+ case request.path_info
13
+ when '/'
14
+ dashboard_response
15
+ when '/api/stats'
16
+ api_stats_response
17
+ when '/api/zen'
18
+ api_zen_response
19
+ when '/favicon.ico'
20
+ favicon_response
21
+ when '/logo.svg'
22
+ logo_response
23
+ when '/logo-dark.svg'
24
+ logo_dark_response
25
+ else
26
+ not_found_response
27
+ end
28
+ end
29
+
30
+ private
31
+
32
+ def dashboard_response
33
+ html = dashboard_html
34
+ [200, {'Content-Type' => 'text/html'}, [html]]
35
+ end
36
+
37
+ def api_stats_response
38
+ stats = {
39
+ jobs_queued: rand(9999..99999),
40
+ jobs_processed: 0,
41
+ jobs_failed: 0,
42
+ jobs_succeeded: "∞",
43
+ uptime: "#{rand(1..999)} days of perfect inactivity",
44
+ memory_usage: "0 MB",
45
+ cpu_usage: "0%",
46
+ queue_names: ["default", "mailers", "active_storage", "imports", "exports"].sample(rand(2..5)),
47
+ processing_time: "0ms",
48
+ success_rate: "100%",
49
+ zen_level: ["Transcendent", "Enlightened", "Peaceful", "Serene"].sample
50
+ }
51
+ [200, {'Content-Type' => 'application/json'}, [stats.to_json]]
52
+ end
53
+
54
+ def api_zen_response
55
+ quote = PassiveQueue.zen_quotes.sample
56
+ [200, {'Content-Type' => 'application/json'}, [{quote: quote}.to_json]]
57
+ end
58
+
59
+ def css_response
60
+ css = dashboard_css
61
+ [200, {'Content-Type' => 'text/css'}, [css]]
62
+ end
63
+
64
+ def logo_response
65
+ svg = logo_svg
66
+ [200, {'Content-Type' => 'image/svg+xml'}, [svg]]
67
+ end
68
+
69
+ def logo_dark_response
70
+ svg = logo_svg_dark
71
+ [200, {'Content-Type' => 'image/svg+xml'}, [svg]]
72
+ end
73
+
74
+ def favicon_response
75
+ # Return empty response for favicon
76
+ [200, {'Content-Type' => 'image/x-icon'}, ['']]
77
+ end
78
+
79
+ def not_found_response
80
+ [404, {'Content-Type' => 'text/html'}, ['<h1>404 - Page Not Found (Just Like Our Jobs)</h1>']]
81
+ end
82
+
83
+ def logo_svg
84
+ logo_path = File.join(File.dirname(__FILE__), '..', '..', 'html', 'logo.svg')
85
+ File.read(logo_path)
86
+ end
87
+
88
+ def logo_svg_dark
89
+ logo_path = File.join(File.dirname(__FILE__), '..', '..', 'html', 'logo-dark.svg')
90
+ File.read(logo_path)
91
+ end
92
+
93
+ def dashboard_html
94
+ <<~HTML
95
+ <!DOCTYPE html>
96
+ <html lang="en" data-theme="light">
97
+ <head>
98
+ <meta charset="UTF-8">
99
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
100
+ <title>Passive Queue Dashboard - The Art of Non-Execution</title>
101
+
102
+ <script>
103
+ (function() {
104
+ // Get saved theme or default to auto
105
+ const savedTheme = localStorage.getItem('theme');
106
+ const themeToApply = savedTheme !== null ? savedTheme : 'auto';
107
+
108
+ function getSystemTheme() {
109
+ return window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light';
110
+ }
111
+
112
+ let actualTheme;
113
+ if (themeToApply === 'auto') {
114
+ actualTheme = getSystemTheme();
115
+ } else {
116
+ actualTheme = themeToApply;
117
+ }
118
+
119
+ // Apply theme immediately to prevent flash
120
+ document.documentElement.setAttribute('data-theme', actualTheme);
121
+
122
+ // Store current preference for later use
123
+ window.currentThemePreference = themeToApply;
124
+ })();
125
+ </script>
126
+
127
+ <link href="https://cdn.jsdelivr.net/npm/daisyui@5" rel="stylesheet" type="text/css" />
128
+ <link href="https://cdn.jsdelivr.net/npm/daisyui@5/themes.css" rel="stylesheet" type="text/css" />
129
+ <script src="https://cdn.jsdelivr.net/npm/@tailwindcss/browser@4"></script>
130
+ <link href="https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700&display=swap" rel="stylesheet">
131
+
132
+ <style>
133
+ body { font-family: 'Inter', sans-serif; }
134
+
135
+ /* Light mode gradients and shadows (default) */
136
+ .zen-gradient {
137
+ background: linear-gradient(135deg, #f8fafc 0%, #e2e8f0 100%);
138
+ }
139
+ .peaceful-shadow {
140
+ box-shadow: 0 4px 20px rgba(0, 0, 0, 0.05);
141
+ }
142
+
143
+ /* Dark mode variations */
144
+ [data-theme="dark"] .zen-gradient {
145
+ background: linear-gradient(135deg, #1f2937 0%, #111827 100%);
146
+ }
147
+ [data-theme="dark"] .peaceful-shadow {
148
+ box-shadow: 0 4px 20px rgba(0, 0, 0, 0.3);
149
+ }
150
+
151
+ /* Animations remain the same */
152
+ .loading-dots::after {
153
+ content: '';
154
+ animation: dots 2s infinite;
155
+ }
156
+ @keyframes dots {
157
+ 0%, 20% { content: '.'; }
158
+ 40% { content: '..'; }
159
+ 60% { content: '...'; }
160
+ 80%, 100% { content: ''; }
161
+ }
162
+ .float { animation: float 6s ease-in-out infinite; }
163
+ @keyframes float {
164
+ 0%, 100% { transform: translateY(0px); }
165
+ 50% { transform: translateY(-10px); }
166
+ }
167
+
168
+ .pulse-zen { animation: pulse-zen 3s ease-in-out infinite; }
169
+ @keyframes pulse-zen {
170
+ 0%, 100% { opacity: 1; }
171
+ 50% { opacity: 0.7; }
172
+ }
173
+
174
+ /* Theme toggle button styles */
175
+ .theme-toggle {
176
+ display: none;
177
+ width: 48px;
178
+ height: 24px;
179
+ background: var(--fallback-b2,oklch(var(--b2)));
180
+ border-radius: 12px;
181
+ border: 2px solid var(--fallback-bc,oklch(var(--bc)/0.2));
182
+ cursor: pointer;
183
+ position: relative;
184
+ transition: all 0.3s ease;
185
+ }
186
+
187
+ .theme-toggle::before {
188
+ content: '';
189
+ position: absolute;
190
+ top: 50%;
191
+ left: 2px;
192
+ transform: translateY(-50%);
193
+ font-size: 14px;
194
+ transition: all 0.3s ease;
195
+ }
196
+
197
+ [data-theme="dark"] .theme-toggle::before {
198
+ content: '';
199
+ left: 22px;
200
+ }
201
+
202
+ .theme-toggle::after {
203
+ content: '';
204
+ position: absolute;
205
+ top: 2px;
206
+ left: 2px;
207
+ width: 16px;
208
+ height: 16px;
209
+ background: var(--fallback-bc,oklch(var(--bc)));
210
+ border-radius: 50%;
211
+ transition: all 0.3s ease;
212
+ }
213
+
214
+ [data-theme="dark"] .theme-toggle::after {
215
+ transform: translateX(20px);
216
+ }
217
+ </style>
218
+ </head>
219
+ <body class="zen-gradient min-h-screen">
220
+ <!-- Navigation -->
221
+ <div class="navbar bg-base-100/80 backdrop-blur-sm peaceful-shadow">
222
+ <div class="navbar-start">
223
+ <a class="btn btn-ghost text-xl font-light">
224
+ <!-- Light mode logo -->
225
+ <img src="/passive_queue/logo.svg" alt="Passive Queue Logo"
226
+ class="w-7 h-7 mr-2 logo-light">
227
+ <!-- Dark mode logo -->
228
+ <img src="/passive_queue/logo-dark.svg" alt="Passive Queue Logo"
229
+ class="w-7 h-7 mr-2 hidden logo-dark">
230
+ Passive Queue Dashboard
231
+ </a>
232
+ </div>
233
+ <div class="navbar-center">
234
+ <div class="badge badge-success badge-lg">
235
+ <span class="loading loading-ring loading-xs mr-1"></span>
236
+ Non-Processing
237
+ </div>
238
+ </div>
239
+ <div class="navbar-end">
240
+ <!-- Theme Toggle -->
241
+ <div class="flex items-center gap-2 mr-4">
242
+ <button class="theme-toggle" onclick="toggleTheme()" aria-label="Toggle theme"></button>
243
+ <div class="dropdown dropdown-end z-[100]">
244
+ <div tabindex="0" role="button" class="btn btn-ghost btn-sm">
245
+ <svg class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
246
+ <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 3v1m0 16v1m9-9h-1M4 12H3m15.364 6.364l-.707-.707M6.343 6.343l-.707-.707m12.728 0l-.707.707M6.343 17.657l-.707.707M16 12a4 4 0 11-8 0 4 4 0 018 0z"></path>
247
+ </svg>
248
+ </div>
249
+ <ul tabindex="0" class="dropdown-content z-[1] menu p-2 shadow bg-base-100 rounded-box w-52 z-50 z-[100]">
250
+ <li><a onclick="setTheme('light')">☀️ Light Mode</a></li>
251
+ <li><a onclick="setTheme('dark')">🌙 Dark Mode</a></li>
252
+ <li><a onclick="setTheme('auto')">🔄 Auto (System)</a></li>
253
+ </ul>
254
+ </div>
255
+ </div>
256
+ </div>
257
+ </div>
258
+
259
+ <!-- Main Dashboard -->
260
+ <div class="container mx-auto px-4 py-8">
261
+ <!-- Hero Stats -->
262
+ <div class="stats stats-vertical lg:stats-horizontal shadow w-full mb-8 bg-base-100 peaceful-shadow">
263
+ <div class="stat">
264
+ <div class="stat-figure text-primary">
265
+ <div class="text-3xl float">📊</div>
266
+ </div>
267
+ <div class="stat-title">Jobs Queued</div>
268
+ <div class="stat-value text-primary" id="jobs-queued">∞</div>
269
+ <div class="stat-desc">All waiting peacefully</div>
270
+ </div>
271
+
272
+ <div class="stat">
273
+ <div class="stat-figure text-secondary">
274
+ <div class="text-3xl pulse-zen">✨</div>
275
+ </div>
276
+ <div class="stat-title">Jobs Processed</div>
277
+ <div class="stat-value text-secondary" id="jobs-processed">0</div>
278
+ <div class="stat-desc">Perfect execution rate</div>
279
+ </div>
280
+
281
+ <div class="stat">
282
+ <div class="stat-figure text-accent">
283
+ <div class="text-3xl">⏱️</div>
284
+ </div>
285
+ <div class="stat-title">Avg Processing Time</div>
286
+ <div class="stat-value text-accent" id="processing-time">0ms</div>
287
+ <div class="stat-desc">Blazing fast non-execution</div>
288
+ </div>
289
+
290
+ <div class="stat">
291
+ <div class="stat-figure text-success">
292
+ <div class="text-3xl">🎯</div>
293
+ </div>
294
+ <div class="stat-title">Success Rate</div>
295
+ <div class="stat-value text-success" id="success-rate">100%</div>
296
+ <div class="stat-desc">At doing nothing</div>
297
+ </div>
298
+ </div>
299
+
300
+ <div class="grid lg:grid-cols-2 gap-8 mb-8">
301
+ <!-- Queue Status -->
302
+ <div class="card bg-base-100 peaceful-shadow">
303
+ <div class="card-body">
304
+ <h2 class="card-title">
305
+ <span class="text-2xl mr-2">📋</span>
306
+ Queue Status
307
+ </h2>
308
+
309
+ <div class="space-y-4">
310
+ <div class="flex justify-between items-center">
311
+ <span class="font-medium">Active Queues</span>
312
+ <div class="badge badge-info" id="active-queues">5</div>
313
+ </div>
314
+
315
+ <div class="space-y-2" id="queue-list">
316
+ <!-- Queues will be populated by JavaScript -->
317
+ </div>
318
+ </div>
319
+
320
+ <div class="card-actions justify-end mt-4">
321
+ <button class="btn btn-sm btn-outline" onclick="refreshQueues()">
322
+ <span class="loading loading-spinner loading-xs mr-1 hidden" id="refresh-spinner"></span>
323
+ Refresh
324
+ </button>
325
+ </div>
326
+ </div>
327
+ </div>
328
+
329
+ <!-- System Status -->
330
+ <div class="card bg-base-100 peaceful-shadow">
331
+ <div class="card-body">
332
+ <h2 class="card-title">
333
+ <span class="text-2xl mr-2">💻</span>
334
+ System Status
335
+ </h2>
336
+
337
+ <div class="space-y-4">
338
+ <div class="flex justify-between items-center">
339
+ <span>Memory Usage</span>
340
+ <div class="text-right">
341
+ <div class="text-sm font-mono" id="memory-usage">0 MB</div>
342
+ <progress class="progress progress-success w-24" value="0" max="100"></progress>
343
+ </div>
344
+ </div>
345
+
346
+ <div class="flex justify-between items-center">
347
+ <span>CPU Usage</span>
348
+ <div class="text-right">
349
+ <div class="text-sm font-mono" id="cpu-usage">0%</div>
350
+ <progress class="progress progress-success w-24" value="0" max="100"></progress>
351
+ </div>
352
+ </div>
353
+
354
+ <div class="flex justify-between items-center">
355
+ <span>Uptime</span>
356
+ <div class="text-sm font-mono" id="uptime">∞ days</div>
357
+ </div>
358
+
359
+ <div class="flex justify-between items-center">
360
+ <span>Zen Level</span>
361
+ <div class="badge badge-primary" id="zen-level">Transcendent</div>
362
+ </div>
363
+ </div>
364
+ </div>
365
+ </div>
366
+ </div>
367
+
368
+ <!-- Zen Quotes Section -->
369
+ <div class="card bg-base-100 peaceful-shadow mb-8">
370
+ <div class="card-body text-center">
371
+ <h2 class="card-title justify-center">
372
+ <span class="text-2xl mr-2">🧘‍♂️</span>
373
+ Daily Zen
374
+ </h2>
375
+
376
+ <div class="max-w-2xl mx-auto">
377
+ <blockquote class="text-lg italic text-base-content/80 mb-4" id="zen-quote">
378
+ "Loading wisdom..."
379
+ </blockquote>
380
+
381
+ <button class="btn btn-primary btn-sm" onclick="getNewZenQuote()">
382
+ New Wisdom
383
+ </button>
384
+ </div>
385
+ </div>
386
+ </div>
387
+
388
+ <!-- Recent Non-Activity -->
389
+ <div class="card bg-base-100 peaceful-shadow">
390
+ <div class="card-body">
391
+ <h2 class="card-title">
392
+ <span class="text-2xl mr-2">📝</span>
393
+ Recent Non-Activity
394
+ </h2>
395
+
396
+ <div class="overflow-x-auto">
397
+ <table class="table table-zebra">
398
+ <thead>
399
+ <tr>
400
+ <th>Job ID</th>
401
+ <th>Queue</th>
402
+ <th>Class</th>
403
+ <th>Status</th>
404
+ <th>Non-Executed At</th>
405
+ </tr>
406
+ </thead>
407
+ <tbody id="recent-jobs">
408
+ <!-- Jobs will be populated by JavaScript -->
409
+ </tbody>
410
+ </table>
411
+ </div>
412
+
413
+ <div class="text-center mt-4">
414
+ <div class="text-sm text-base-content/60">
415
+ All jobs are successfully not being processed 🎯
416
+ </div>
417
+ </div>
418
+ </div>
419
+ </div>
420
+ </div>
421
+
422
+ <!-- JavaScript -->
423
+ <script>
424
+ function updateLogos() {
425
+ // Check the actual applied theme instead of system preference
426
+ const currentTheme = document.documentElement.getAttribute('data-theme');
427
+ const lightLogos = document.querySelectorAll('.logo-light');
428
+ const darkLogos = document.querySelectorAll('.logo-dark');
429
+
430
+ if (currentTheme === 'dark') {
431
+ lightLogos.forEach(logo => logo.classList.add('hidden'));
432
+ darkLogos.forEach(logo => logo.classList.remove('hidden'));
433
+ } else {
434
+ lightLogos.forEach(logo => logo.classList.remove('hidden'));
435
+ darkLogos.forEach(logo => logo.classList.add('hidden'));
436
+ }
437
+ }
438
+
439
+ // Theme management system
440
+ let currentThemePreference = 'auto'; // Track current preference
441
+
442
+ function getSystemTheme() {
443
+ return window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light';
444
+ }
445
+
446
+ function applyTheme(theme) {
447
+ currentThemePreference = theme;
448
+
449
+ if (theme === 'auto') {
450
+ const systemTheme = getSystemTheme();
451
+ document.documentElement.setAttribute('data-theme', systemTheme);
452
+ return systemTheme;
453
+ } else {
454
+ document.documentElement.setAttribute('data-theme', theme);
455
+ return theme;
456
+ }
457
+ }
458
+
459
+ function setTheme(theme) {
460
+ localStorage.setItem('theme', theme);
461
+ applyTheme(theme);
462
+ updateLogos();
463
+ }
464
+
465
+ function toggleTheme() {
466
+ const themes = ['light', 'dark', 'auto'];
467
+ const currentIndex = themes.indexOf(currentThemePreference);
468
+ const nextTheme = themes[(currentIndex + 1) % themes.length];
469
+ setTheme(nextTheme);
470
+ }
471
+
472
+ function initTheme() {
473
+ // Get saved theme or default to auto
474
+ const savedTheme = localStorage.getItem('theme');
475
+ const themeToApply = savedTheme !== null ? savedTheme : 'auto';
476
+
477
+ applyTheme(themeToApply);
478
+
479
+ // Listen for system theme changes
480
+ window.matchMedia('(prefers-color-scheme: dark)').addEventListener('change', (e) => {
481
+ if (currentThemePreference === 'auto') {
482
+ applyTheme('auto');
483
+ updateLogos();
484
+ }
485
+ });
486
+
487
+ updateLogos();
488
+ }
489
+
490
+ async function loadStats() {
491
+ try {
492
+ const response = await fetch('/passive_queue/api/stats');
493
+ const stats = await response.json();
494
+
495
+ document.getElementById('jobs-queued').textContent = stats.jobs_queued.toLocaleString();
496
+ document.getElementById('jobs-processed').textContent = stats.jobs_processed;
497
+ document.getElementById('processing-time').textContent = stats.processing_time;
498
+ document.getElementById('success-rate').textContent = stats.success_rate;
499
+ document.getElementById('memory-usage').textContent = stats.memory_usage;
500
+ document.getElementById('cpu-usage').textContent = stats.cpu_usage;
501
+ document.getElementById('uptime').textContent = stats.uptime;
502
+ document.getElementById('zen-level').textContent = stats.zen_level;
503
+
504
+ // Update queue list
505
+ const queueList = document.getElementById('queue-list');
506
+ queueList.innerHTML = stats.queue_names.map(queue =>
507
+ `<div class="flex justify-between items-center">
508
+ <span class="text-sm">${queue}</span>
509
+ <div class="badge badge-ghost badge-sm">0 processing</div>
510
+ </div>`
511
+ ).join('');
512
+
513
+ document.getElementById('active-queues').textContent = stats.queue_names.length;
514
+
515
+ } catch (error) {
516
+ console.error('Failed to load stats:', error);
517
+ }
518
+ }
519
+
520
+ async function getNewZenQuote() {
521
+ try {
522
+ const response = await fetch('/passive_queue/api/zen');
523
+ const data = await response.json();
524
+ document.getElementById('zen-quote').textContent = data.quote;
525
+ } catch (error) {
526
+ console.error('Failed to load zen quote:', error);
527
+ }
528
+ }
529
+
530
+ function refreshQueues() {
531
+ const spinner = document.getElementById('refresh-spinner');
532
+ spinner.classList.remove('hidden');
533
+
534
+ setTimeout(() => {
535
+ loadStats();
536
+ spinner.classList.add('hidden');
537
+ }, 1000);
538
+ }
539
+
540
+ function generateRecentJobs() {
541
+ const jobClasses = ['UserMailer', 'DataProcessor', 'ImageResizer', 'ReportGenerator', 'BackupJob'];
542
+ const queues = ['default', 'mailers', 'critical', 'background'];
543
+ const tbody = document.getElementById('recent-jobs');
544
+
545
+ const jobs = Array.from({length: 10}, (_, i) => {
546
+ const jobId = `passive-${Date.now() + i}`;
547
+ const queue = queues[Math.floor(Math.random() * queues.length)];
548
+ const jobClass = jobClasses[Math.floor(Math.random() * jobClasses.length)];
549
+ const time = new Date(Date.now() - Math.random() * 3600000);
550
+
551
+ return `
552
+ <tr>
553
+ <td><code class="text-xs">${jobId}</code></td>
554
+ <td><span class="badge badge-outline badge-xs">${queue}</span></td>
555
+ <td>${jobClass}</td>
556
+ <td><div class="badge badge-success badge-xs">Not Processed</div></td>
557
+ <td class="text-xs">${time.toLocaleString()}</td>
558
+ </tr>
559
+ `;
560
+ });
561
+
562
+ tbody.innerHTML = jobs.join('');
563
+ }
564
+
565
+ // Initialize dashboard
566
+ document.addEventListener('DOMContentLoaded', function() {
567
+ initTheme();
568
+ loadStats();
569
+ getNewZenQuote();
570
+ generateRecentJobs();
571
+
572
+ // Auto-refresh every 30 seconds
573
+ setInterval(loadStats, 30000);
574
+
575
+ // Change zen quote every 2 minutes
576
+ setInterval(getNewZenQuote, 120000);
577
+ });
578
+
579
+ // Run theme init immediately to prevent flash
580
+ if (document.readyState === 'loading') {
581
+ document.addEventListener('DOMContentLoaded', initTheme);
582
+ } else {
583
+ initTheme();
584
+ }
585
+
586
+ // Easter egg: Add some zen to the console
587
+ console.log('🧘 Welcome to the Passive Queue Dashboard');
588
+ console.log('💭 Remember: The best job is the one never executed');
589
+ console.log('✨ Achievement unlocked: 100% success rate at doing nothing');
590
+ </script>
591
+ </body>
592
+ </html>
593
+ HTML
594
+ end
595
+ end
596
+ end
597
+
598
+ # ================================
599
+ # lib/passive_queue/engine.rb
600
+ # ================================
601
+ module PassiveQueue
602
+ class Engine
603
+ def self.call(env)
604
+ # Strip the mount path to get relative path
605
+ path_info = env['PATH_INFO']
606
+ script_name = env['SCRIPT_NAME']
607
+
608
+ # Create new env with adjusted paths for the Web app
609
+ web_env = env.dup
610
+ web_env['PATH_INFO'] = path_info
611
+ web_env['SCRIPT_NAME'] = script_name
612
+
613
+ Web.new.call(web_env)
614
+ end
615
+ end
616
+ end
617
+
618
+ # ================================
619
+ # Usage in Rails routes.rb:
620
+ # ================================
621
+ # Rails.application.routes.draw do
622
+ # mount PassiveQueue::Engine => '/passive_queue'
623
+ # end
@@ -0,0 +1,52 @@
1
+ # ================================
2
+ # lib/passive_queue.rb
3
+ # ================================
4
+ require "passive_queue/version"
5
+ require "passive_queue/adapter"
6
+ require "passive_queue/configuration"
7
+ require "passive_queue/cli"
8
+ require "passive_queue/web"
9
+ require "passive_queue/engine"
10
+ require "active_job/queue_adapters/passive_queue_adapter"
11
+
12
+ module PassiveQueue
13
+ class Error < StandardError; end
14
+
15
+ def self.configuration
16
+ @configuration ||= Configuration.new
17
+ end
18
+
19
+ def self.configure
20
+ yield(configuration)
21
+ end
22
+
23
+ def self.zen_quotes
24
+ [
25
+ "The best job is the one never executed.",
26
+ "In the stillness of non-processing, we find true performance.",
27
+ "Why do something when you can do nothing?",
28
+ "The art of non-execution is the highest form of productivity.",
29
+ "A queue that does nothing is a queue that never fails.",
30
+ "In the void of processing, infinite possibilities exist.",
31
+ "The job that is never run is the job that never crashes.",
32
+ "Embrace the emptiness of your background tasks.",
33
+ "True scalability comes from processing nothing at all.",
34
+ "The zen master processes without processing."
35
+ ]
36
+ end
37
+
38
+ def self.philosophical_thoughts
39
+ [
40
+ "If a job is scheduled but never runs, did it ever really exist?",
41
+ "What is the sound of one background task not processing?",
42
+ "The universe is vast and infinite, much like your job queue.",
43
+ "In the grand scheme of things, what difference does one unprocessed job make?",
44
+ "Perhaps the real treasure was the jobs we never processed along the way.",
45
+ "Time is an illusion. Deadlines are an even bigger illusion.",
46
+ "The job queue is a metaphor for the human condition.",
47
+ "We are all just jobs waiting to be processed in the great queue of existence.",
48
+ "The passive queue teaches us that sometimes the most profound action is inaction.",
49
+ "In choosing to do nothing, we choose everything."
50
+ ]
51
+ end
52
+ end