sidekiq 6.4.1 → 6.5.10

Sign up to get free protection for your applications and to get access to all the features.
Files changed (67) hide show
  1. checksums.yaml +4 -4
  2. data/Changes.md +107 -1
  3. data/README.md +1 -1
  4. data/bin/sidekiqload +18 -12
  5. data/lib/sidekiq/api.rb +222 -71
  6. data/lib/sidekiq/cli.rb +51 -37
  7. data/lib/sidekiq/client.rb +27 -28
  8. data/lib/sidekiq/component.rb +65 -0
  9. data/lib/sidekiq/delay.rb +1 -1
  10. data/lib/sidekiq/extensions/generic_proxy.rb +1 -1
  11. data/lib/sidekiq/fetch.rb +18 -16
  12. data/lib/sidekiq/job_retry.rb +73 -52
  13. data/lib/sidekiq/job_util.rb +15 -9
  14. data/lib/sidekiq/launcher.rb +37 -33
  15. data/lib/sidekiq/logger.rb +5 -19
  16. data/lib/sidekiq/manager.rb +28 -25
  17. data/lib/sidekiq/metrics/deploy.rb +47 -0
  18. data/lib/sidekiq/metrics/query.rb +153 -0
  19. data/lib/sidekiq/metrics/shared.rb +94 -0
  20. data/lib/sidekiq/metrics/tracking.rb +134 -0
  21. data/lib/sidekiq/middleware/chain.rb +82 -38
  22. data/lib/sidekiq/middleware/current_attributes.rb +18 -12
  23. data/lib/sidekiq/middleware/i18n.rb +6 -4
  24. data/lib/sidekiq/middleware/modules.rb +21 -0
  25. data/lib/sidekiq/monitor.rb +2 -2
  26. data/lib/sidekiq/paginator.rb +11 -3
  27. data/lib/sidekiq/processor.rb +47 -41
  28. data/lib/sidekiq/rails.rb +25 -8
  29. data/lib/sidekiq/redis_client_adapter.rb +154 -0
  30. data/lib/sidekiq/redis_connection.rb +80 -49
  31. data/lib/sidekiq/ring_buffer.rb +29 -0
  32. data/lib/sidekiq/scheduled.rb +53 -24
  33. data/lib/sidekiq/testing/inline.rb +4 -4
  34. data/lib/sidekiq/testing.rb +37 -36
  35. data/lib/sidekiq/transaction_aware_client.rb +45 -0
  36. data/lib/sidekiq/version.rb +1 -1
  37. data/lib/sidekiq/web/action.rb +3 -3
  38. data/lib/sidekiq/web/application.rb +21 -5
  39. data/lib/sidekiq/web/csrf_protection.rb +2 -2
  40. data/lib/sidekiq/web/helpers.rb +20 -7
  41. data/lib/sidekiq/web.rb +5 -1
  42. data/lib/sidekiq/worker.rb +24 -16
  43. data/lib/sidekiq.rb +106 -31
  44. data/sidekiq.gemspec +2 -2
  45. data/web/assets/javascripts/application.js +59 -26
  46. data/web/assets/javascripts/chart.min.js +13 -0
  47. data/web/assets/javascripts/chartjs-plugin-annotation.min.js +7 -0
  48. data/web/assets/javascripts/dashboard.js +0 -17
  49. data/web/assets/javascripts/graph.js +16 -0
  50. data/web/assets/javascripts/metrics.js +262 -0
  51. data/web/assets/stylesheets/application.css +45 -3
  52. data/web/locales/el.yml +43 -19
  53. data/web/locales/en.yml +7 -0
  54. data/web/locales/ja.yml +7 -0
  55. data/web/locales/pt-br.yml +27 -9
  56. data/web/locales/zh-cn.yml +36 -11
  57. data/web/locales/zh-tw.yml +32 -7
  58. data/web/views/_nav.erb +1 -1
  59. data/web/views/_summary.erb +1 -1
  60. data/web/views/busy.erb +9 -4
  61. data/web/views/dashboard.erb +1 -0
  62. data/web/views/metrics.erb +69 -0
  63. data/web/views/metrics_for_job.erb +87 -0
  64. data/web/views/queue.erb +5 -1
  65. metadata +34 -9
  66. data/lib/sidekiq/exception_handler.rb +0 -27
  67. data/lib/sidekiq/util.rb +0 -108
@@ -0,0 +1,262 @@
1
+ if (window.matchMedia('(prefers-color-scheme: dark)').matches) {
2
+ Chart.defaults.borderColor = "#333"
3
+ Chart.defaults.color = "#aaa"
4
+ }
5
+
6
+ class BaseChart {
7
+ constructor(id, options) {
8
+ this.ctx = document.getElementById(id);
9
+ this.options = options
10
+ this.fallbackColor = "#999";
11
+ this.colors = [
12
+ // Colors taken from https://www.chartjs.org/docs/latest/samples/utils.html
13
+ "#537bc4",
14
+ "#4dc9f6",
15
+ "#f67019",
16
+ "#f53794",
17
+ "#acc236",
18
+ "#166a8f",
19
+ "#00a950",
20
+ "#58595b",
21
+ "#8549ba",
22
+ "#991b1b",
23
+ ];
24
+
25
+ this.chart = new Chart(this.ctx, {
26
+ type: this.options.chartType,
27
+ data: { labels: this.options.labels, datasets: this.datasets },
28
+ options: this.chartOptions,
29
+ });
30
+ }
31
+
32
+ addMarksToChart() {
33
+ this.options.marks.forEach(([bucket, label], i) => {
34
+ this.chart.options.plugins.annotation.annotations[`deploy-${i}`] = {
35
+ type: "line",
36
+ xMin: bucket,
37
+ xMax: bucket,
38
+ borderColor: "rgba(220, 38, 38, 0.4)",
39
+ borderWidth: 2,
40
+ };
41
+ });
42
+ }
43
+ }
44
+
45
+ class JobMetricsOverviewChart extends BaseChart {
46
+ constructor(id, options) {
47
+ super(id, { ...options, chartType: "line" });
48
+ this.swatches = [];
49
+
50
+ this.addMarksToChart();
51
+ this.chart.update();
52
+ }
53
+
54
+ registerSwatch(id) {
55
+ const el = document.getElementById(id);
56
+ el.onchange = () => this.toggle(el.value, el.checked);
57
+ this.swatches[el.value] = el;
58
+ this.updateSwatch(el.value);
59
+ }
60
+
61
+ updateSwatch(kls) {
62
+ const el = this.swatches[kls];
63
+ const ds = this.chart.data.datasets.find((ds) => ds.label == kls);
64
+ el.checked = !!ds;
65
+ el.style.color = ds ? ds.borderColor : null;
66
+ }
67
+
68
+ toggle(kls, visible) {
69
+ if (visible) {
70
+ this.chart.data.datasets.push(this.dataset(kls));
71
+ } else {
72
+ const i = this.chart.data.datasets.findIndex((ds) => ds.label == kls);
73
+ this.colors.unshift(this.chart.data.datasets[i].borderColor);
74
+ this.chart.data.datasets.splice(i, 1);
75
+ }
76
+
77
+ this.updateSwatch(kls);
78
+ this.chart.update();
79
+ }
80
+
81
+ dataset(kls) {
82
+ const color = this.colors.shift() || this.fallbackColor;
83
+
84
+ return {
85
+ label: kls,
86
+ data: this.options.series[kls],
87
+ borderColor: color,
88
+ backgroundColor: color,
89
+ borderWidth: 2,
90
+ pointRadius: 2,
91
+ };
92
+ }
93
+
94
+ get datasets() {
95
+ return Object.entries(this.options.series)
96
+ .filter(([kls, _]) => this.options.visible.includes(kls))
97
+ .map(([kls, _]) => this.dataset(kls));
98
+ }
99
+
100
+ get chartOptions() {
101
+ return {
102
+ aspectRatio: 4,
103
+ scales: {
104
+ y: {
105
+ beginAtZero: true,
106
+ title: {
107
+ text: "Total execution time (sec)",
108
+ display: true,
109
+ },
110
+ },
111
+ },
112
+ interaction: {
113
+ mode: "x",
114
+ },
115
+ plugins: {
116
+ legend: {
117
+ display: false,
118
+ },
119
+ tooltip: {
120
+ callbacks: {
121
+ title: (items) => `${items[0].label} UTC`,
122
+ label: (item) =>
123
+ `${item.dataset.label}: ${item.parsed.y.toFixed(1)} seconds`,
124
+ footer: (items) => {
125
+ const bucket = items[0].label;
126
+ const marks = this.options.marks.filter(([b, _]) => b == bucket);
127
+ return marks.map(([b, msg]) => `Deploy: ${msg}`);
128
+ },
129
+ },
130
+ },
131
+ },
132
+ };
133
+ }
134
+ }
135
+
136
+ class HistTotalsChart extends BaseChart {
137
+ constructor(id, options) {
138
+ super(id, { ...options, chartType: "bar" });
139
+ }
140
+
141
+ get datasets() {
142
+ return [{
143
+ data: this.options.series,
144
+ backgroundColor: this.colors[0],
145
+ borderWidth: 0,
146
+ }];
147
+ }
148
+
149
+ get chartOptions() {
150
+ return {
151
+ aspectRatio: 6,
152
+ scales: {
153
+ y: {
154
+ beginAtZero: true,
155
+ title: {
156
+ text: "Total jobs",
157
+ display: true,
158
+ },
159
+ },
160
+ },
161
+ interaction: {
162
+ mode: "x",
163
+ },
164
+ plugins: {
165
+ legend: {
166
+ display: false,
167
+ },
168
+ tooltip: {
169
+ callbacks: {
170
+ label: (item) => `${item.parsed.y} jobs`,
171
+ },
172
+ },
173
+ },
174
+ };
175
+ }
176
+ }
177
+
178
+ class HistBubbleChart extends BaseChart {
179
+ constructor(id, options) {
180
+ super(id, { ...options, chartType: "bubble" });
181
+
182
+ this.addMarksToChart();
183
+ this.chart.update();
184
+ }
185
+
186
+ get datasets() {
187
+ const data = [];
188
+ let maxCount = 0;
189
+
190
+ Object.entries(this.options.hist).forEach(([bucket, hist]) => {
191
+ hist.forEach((count, histBucket) => {
192
+ if (count > 0) {
193
+ data.push({
194
+ x: bucket,
195
+ // histogram data is ordered fastest to slowest, but this.histIntervals is
196
+ // slowest to fastest (so it displays correctly on the chart).
197
+ y:
198
+ this.options.histIntervals[this.options.histIntervals.length - 1 - histBucket] /
199
+ 1000,
200
+ count: count,
201
+ });
202
+
203
+ if (count > maxCount) maxCount = count;
204
+ }
205
+ });
206
+ });
207
+
208
+ // Chart.js will not calculate the bubble size. We have to do that.
209
+ const maxRadius = this.ctx.offsetWidth / this.options.labels.length;
210
+ const minRadius = 1
211
+ const multiplier = (maxRadius / maxCount) * 1.5;
212
+ data.forEach((entry) => {
213
+ entry.r = entry.count * multiplier + minRadius;
214
+ });
215
+
216
+ return [{
217
+ data: data,
218
+ backgroundColor: "#537bc4",
219
+ borderColor: "#537bc4",
220
+ }];
221
+ }
222
+
223
+ get chartOptions() {
224
+ return {
225
+ aspectRatio: 3,
226
+ scales: {
227
+ x: {
228
+ type: "category",
229
+ labels: this.options.labels,
230
+ },
231
+ y: {
232
+ title: {
233
+ text: "Execution time (sec)",
234
+ display: true,
235
+ },
236
+ },
237
+ },
238
+ interaction: {
239
+ mode: "x",
240
+ },
241
+ plugins: {
242
+ legend: {
243
+ display: false,
244
+ },
245
+ tooltip: {
246
+ callbacks: {
247
+ title: (items) => `${items[0].raw.x} UTC`,
248
+ label: (item) =>
249
+ `${item.parsed.y} seconds: ${item.raw.count} job${
250
+ item.raw.count == 1 ? "" : "s"
251
+ }`,
252
+ footer: (items) => {
253
+ const bucket = items[0].raw.x;
254
+ const marks = this.options.marks.filter(([b, _]) => b == bucket);
255
+ return marks.map(([b, msg]) => `Deploy: ${msg}`);
256
+ },
257
+ },
258
+ },
259
+ },
260
+ };
261
+ }
262
+ }
@@ -67,10 +67,15 @@ body {
67
67
  padding: 0 20px;
68
68
  }
69
69
 
70
- h3 {
70
+ h1, h2, h3 {
71
+ font-size: 24px;
71
72
  line-height: 45px;
72
73
  }
73
74
 
75
+ .header-with-subheader h2 {
76
+ margin-top: -18px;
77
+ }
78
+
74
79
  .centered {
75
80
  text-align: center;
76
81
  }
@@ -202,8 +207,7 @@ table .table-checkbox label {
202
207
 
203
208
  .navbar .navbar-brand .status {
204
209
  color: #585454;
205
- display: inline-block;
206
- width: 75px;
210
+ display: inline;
207
211
  }
208
212
 
209
213
 
@@ -955,3 +959,41 @@ div.interval-slider input {
955
959
  padding: 3px 7px;
956
960
  margin-left: 5px;
957
961
  }
962
+
963
+ .metrics-swatch-wrapper {
964
+ display: flex;
965
+ align-items: center;
966
+ gap: 6px;
967
+ }
968
+
969
+ .metrics-swatch[type=checkbox] {
970
+ display: inline-block;
971
+ width: 16px;
972
+ height: 16px;
973
+ margin: 0;
974
+ border-radius: 2px;
975
+ appearance: none;
976
+ -webkit-appearance: none;
977
+ -moz-appearance: none;
978
+ border: 1px solid #bbb;
979
+ color: white;
980
+ background-color: currentColor;
981
+ }
982
+
983
+ /* We need to add the checkmark since we've taken over the appearance */
984
+ .metrics-swatch[type=checkbox]:checked {
985
+ border-color: currentColor;
986
+ background-image: url("data:image/svg+xml,%3csvg viewBox='0 0 16 16' fill='white' xmlns='http://www.w3.org/2000/svg'%3e%3cpath d='M12.207 4.793a1 1 0 010 1.414l-5 5a1 1 0 01-1.414 0l-2-2a1 1 0 011.414-1.414L6.5 9.086l4.293-4.293a1 1 0 011.414 0z'/%3e%3c/svg%3e");
987
+ background-size: 100% 100%;
988
+ background-position: center;
989
+ background-repeat: no-repeat;
990
+ }
991
+
992
+ .metrics-swatch[type=checkbox]:focus {
993
+ outline: 1px solid #888;
994
+ outline-offset: 2px;
995
+ }
996
+
997
+ canvas {
998
+ margin: 20px 0 30px;
999
+ }
data/web/locales/el.yml CHANGED
@@ -6,11 +6,12 @@ el: # <---- change this to your locale code
6
6
  Namespace: Namespace
7
7
  Realtime: Τρέχουσα Κατάσταση
8
8
  History: Ιστορικό
9
- Busy: Απασχολημένο
10
- Processed: Επεξεργάστηκε
11
- Failed: Απέτυχε
12
- Scheduled: Προγραματίστηκε
13
- Retries: Προσπάθειες
9
+ Busy: Υπό επεξεργασία
10
+ Utilization: Σε χρήση
11
+ Processed: Επεξεργάστηκαν
12
+ Failed: Απέτυχαν
13
+ Scheduled: Προγραμματισμένα
14
+ Retries: Επαναλήψεις
14
15
  Enqueued: Μπήκαν στην στοίβα
15
16
  Worker: Εργάτης
16
17
  LivePoll: Τρέχουσα Κατάσταση
@@ -20,40 +21,42 @@ el: # <---- change this to your locale code
20
21
  Job: Εργασία
21
22
  Arguments: Ορίσματα
22
23
  Extras: Extras
23
- Started: Ξεκίνησαν
24
+ Started: Ξεκίνησε
24
25
  ShowAll: Εμφάνιση Όλων
25
26
  CurrentMessagesInQueue: Τρέχουσες εργασίες <span class='title'>%{queue}</span>
26
27
  Delete: Διαγραφή
27
28
  AddToQueue: Προσθήκη στην στοίβα
28
- AreYouSureDeleteJob: Θέλετε να διαγράψετε την εργασία αυτη;
29
- AreYouSureDeleteQueue: Θέλετε να διαγράψετε την %{queue} στοίβα?
29
+ AreYouSureDeleteJob: Θέλετε να διαγράψετε αυτή την εργασία;
30
+ AreYouSureDeleteQueue: Θέλετε να διαγράψετε την στοίβα %{queue}; Αυτό θα διαγράψει όλες τις εργασίες εντός της στοίβας, θα εμφανιστεί ξανά εάν προωθήσετε περισσότερες εργασίες σε αυτήν στο μέλλον.
30
31
  Queues: Στοίβες
31
32
  Size: Μέγεθος
32
33
  Actions: Ενέργειες
33
- NextRetry: Επόμενη προσπάθεια
34
- RetryCount: Αριθμός προσπαθειών
35
- RetryNow: Προσπάθησε τώρα
36
- LastRetry: Τελευταία προσπάθεια
34
+ NextRetry: Επόμενη Προσπάθεια
35
+ RetryCount: Αριθμός Προσπαθειών
36
+ RetryNow: Επανάληψη Τώρα
37
+ # Kill: Kill
38
+ LastRetry: Τελευταία Προσπάθεια
37
39
  OriginallyFailed: Αρχικές Αποτυχίες
38
- AreYouSure: Είστε σίγουρος?
39
- DeleteAll: Διαγραφή όλων
40
+ AreYouSure: Είστε σίγουρος;
41
+ DeleteAll: Διαγραφή Όλων
40
42
  RetryAll: Επανάληψη Όλων
41
- NoRetriesFound: Δεν βρέθηκαν προσπάθειες
43
+ # KillAll: Kill All
44
+ NoRetriesFound: Δεν βρέθηκαν εργασίες προς επαναλήψη
42
45
  Error: Σφάλμα
43
46
  ErrorClass: Κλάση σφάλματος
44
47
  ErrorMessage: Μήνυμα Σφάλματος
45
- ErrorBacktrace: Σφάλμα Backtrace
48
+ ErrorBacktrace: Backtrace Σφάλματος
46
49
  GoBack: ← Πίσω
47
50
  NoScheduledFound: Δεν βρέθηκαν προγραμματισμένες εργασίες
48
51
  When: Πότε
49
52
  ScheduledJobs: Προγραμματισμένες Εργασίες
50
- idle: αδρανής
51
- active: ενεργή
53
+ idle: αδρανές
54
+ active: ενεργό
52
55
  Version: Έκδοση
53
56
  Connections: Συνδέσεις
54
57
  MemoryUsage: Χρήση Μνήμης
55
58
  PeakMemoryUsage: Μέγιστη Χρήση Μνήμης
56
- Uptime: Διάρκεια Λειτουργείας (ημέρες)
59
+ Uptime: Ημέρες Λειτουργίας
57
60
  OneWeek: 1 εβδομάδα
58
61
  OneMonth: 1 μήνας
59
62
  ThreeMonths: 3 μήνες
@@ -62,7 +65,28 @@ el: # <---- change this to your locale code
62
65
  DeadJobs: Αδρανείς Εργασίες
63
66
  NoDeadJobsFound: Δεν βρέθηκαν αδρανείς εργασίες
64
67
  Dead: Αδρανείς
68
+ Process: Διεργασία
65
69
  Processes: Διεργασίες
70
+ Name: Όνομα
66
71
  Thread: Νήμα
67
72
  Threads: Νήματα
68
73
  Jobs: Εργασίες
74
+ Paused: Σε παύση
75
+ Stop: Διακοπή
76
+ Quiet: Σίγαση
77
+ StopAll: Διακοπή Όλων
78
+ QuietAll: Σίγαση Όλων
79
+ PollingInterval: Συχνότητα Ανανέωσης
80
+ Plugins: Πρόσθετα
81
+ NotYetEnqueued: Δεν προστέθηκε στην στοίβα ακόμη
82
+ CreatedAt: Δημιουργήθηκε στις
83
+ BackToApp: Πίσω στην Εφαρμογή
84
+ Latency: Καθυστέρηση
85
+ Pause: Παύση
86
+ Unpause: Κατάργηση Παύσης
87
+ Metrics: Μετρήσεις
88
+ NoDataFound: Δεν βρέθηκαν δεδομένα
89
+ ExecutionTime: Συνολικός Χρόνος Εκτέλεσης
90
+ AvgExecutionTime: Μέσος Χρόνος Εκτέλεσης
91
+ # Context: Context
92
+
data/web/locales/en.yml CHANGED
@@ -84,3 +84,10 @@ en: # <---- change this to your locale code
84
84
  Latency: Latency
85
85
  Pause: Pause
86
86
  Unpause: Unpause
87
+ Metrics: Metrics
88
+ NoDataFound: No data found
89
+ ExecutionTime: Total Execution Time
90
+ AvgExecutionTime: Average Execution Time
91
+ Context: Context
92
+ Bucket: Bucket
93
+ NoJobMetricsFound: No recent job metrics were found
data/web/locales/ja.yml CHANGED
@@ -84,3 +84,10 @@ ja:
84
84
  Latency: レイテンシ
85
85
  Pause: 一時停止
86
86
  Unpause: 一時停止を解除
87
+ Metrics: メトリクス
88
+ NoDataFound: データが見つかりませんでした
89
+ ExecutionTime: 合計実行時間
90
+ AvgExecutionTime: 平均実行時間
91
+ Context: コンテキスト
92
+ Bucket: バケット
93
+ NoJobMetricsFound: 直近のジョブメトリクスが見つかりませんでした
@@ -8,6 +8,7 @@
8
8
  History: Histórico
9
9
  Busy: Ocupados
10
10
  Processed: Processados
11
+ Utilization: Utilização
11
12
  Failed: Falhas
12
13
  Scheduled: Agendados
13
14
  Retries: Tentativas
@@ -26,18 +27,20 @@
26
27
  Delete: Apagar
27
28
  AddToQueue: Adicionar à fila
28
29
  AreYouSureDeleteJob: Deseja deletar esta tarefa?
29
- AreYouSureDeleteQueue: Deseja deletar a %{queue} fila?
30
+ AreYouSureDeleteQueue: Deseja deletar a fila %{queue}? Isso irá deletar todas as tarefas desta fila.
30
31
  Queues: Filas
31
32
  Size: Tamanho
32
33
  Actions: Ações
33
34
  NextRetry: Próxima Tentativa
34
35
  RetryCount: Número de Tentativas
35
36
  RetryNow: Tentar novamente agora
37
+ Kill: Matar
36
38
  LastRetry: Última tentativa
37
39
  OriginallyFailed: Falhou originalmente
38
40
  AreYouSure: Tem certeza?
39
41
  DeleteAll: Apagar tudo
40
42
  RetryAll: Tentar tudo novamente
43
+ KillAll: Matar todas
41
44
  NoRetriesFound: Nenhuma tentativa encontrada
42
45
  Error: Erro
43
46
  ErrorClass: Classe de erro
@@ -58,11 +61,26 @@
58
61
  OneMonth: 1 mês
59
62
  ThreeMonths: 3 meses
60
63
  SixMonths: 6 meses
61
- Failures : Falhas
62
- DeadJobs : Tarefas mortas
63
- NoDeadJobsFound : Nenhuma tarefa morta foi encontrada
64
- Dead : Morta
65
- Processes : Processos
66
- Thread : Thread
67
- Threads : Threads
68
- Jobs : Tarefas
64
+ Failures: Falhas
65
+ DeadJobs: Tarefas mortas
66
+ NoDeadJobsFound: Nenhuma tarefa morta foi encontrada
67
+ Dead: Morta
68
+ Process: Processo
69
+ Processes: Processos
70
+ Name: Nome
71
+ Thread: Thread
72
+ Threads: Threads
73
+ Jobs: Tarefas
74
+ Paused: Pausado
75
+ Stop: Parar
76
+ Quiet: Silenciar
77
+ StopAll: Parar Todos
78
+ QuietAll: Silenciar Todos
79
+ PollingInterval: Intervalo de Polling
80
+ Plugins: Plug-ins
81
+ NotYetEnqueued: Ainda não enfileirado
82
+ CreatedAt: Criado em
83
+ BackToApp: De volta ao aplicativo
84
+ Latency: Latência
85
+ Pause: Pausar
86
+ Unpause: Despausar
@@ -7,6 +7,7 @@ zh-cn: # <---- change this to your locale code
7
7
  Realtime: 实时
8
8
  History: 历史记录
9
9
  Busy: 执行中
10
+ Utilization: 利用率
10
11
  Processed: 已处理
11
12
  Failed: 已失败
12
13
  Scheduled: 已计划
@@ -17,15 +18,15 @@ zh-cn: # <---- change this to your locale code
17
18
  StopPolling: 停止轮询
18
19
  Queue: 队列
19
20
  Class: 类别
20
- Job: 作业
21
+ Job: 任务
21
22
  Arguments: 参数
22
23
  Extras: 额外的
23
24
  Started: 已开始
24
25
  ShowAll: 显示全部
25
- CurrentMessagesInQueue: 目前在<span class='title'>%{queue}</span>的作业
26
+ CurrentMessagesInQueue: 目前在<span class='title'>%{queue}</span>的任务
26
27
  Delete: 删除
27
28
  AddToQueue: 添加至队列
28
- AreYouSureDeleteJob: 你确定要删除这个作业么?
29
+ AreYouSureDeleteJob: 你确定要删除这个任务么?
29
30
  AreYouSureDeleteQueue: 你确定要删除%{queue}这个队列?
30
31
  Queues: 队列
31
32
  Size: 容量
@@ -33,20 +34,22 @@ zh-cn: # <---- change this to your locale code
33
34
  NextRetry: 下次重试
34
35
  RetryCount: 重试次數
35
36
  RetryNow: 现在重试
37
+ Kill: 终止
36
38
  LastRetry: 最后一次重试
37
39
  OriginallyFailed: 原本已失败
38
40
  AreYouSure: 你确定?
39
- DeleteAll: 删除全部
40
- RetryAll: 重试全部
41
+ DeleteAll: 全部删除
42
+ RetryAll: 全部重试
43
+ KillAll: 全部终止
41
44
  NoRetriesFound: 沒有发现可重试
42
45
  Error: 错误
43
46
  ErrorClass: 错误类别
44
47
  ErrorMessage: 错误消息
45
- ErrorBacktrace: 错误的回调追踪
48
+ ErrorBacktrace: 错误细节
46
49
  GoBack: ← 返回
47
- NoScheduledFound: 沒有发现计划作业
50
+ NoScheduledFound: 沒有发现计划任务
48
51
  When: 当
49
- ScheduledJobs: 计划作业
52
+ ScheduledJobs: 计划任务
50
53
  idle: 闲置
51
54
  active: 活动中
52
55
  Version: 版本
@@ -59,10 +62,32 @@ zh-cn: # <---- change this to your locale code
59
62
  ThreeMonths: 三个月
60
63
  SixMonths: 六个月
61
64
  Failures: 失败
62
- DeadJobs: 已停滞作业
63
- NoDeadJobsFound: 沒有发现任何已停滞的作业
65
+ DeadJobs: 已停滞任务
66
+ NoDeadJobsFound: 沒有发现任何已停滞的任务
64
67
  Dead: 已停滞
68
+ Process: 进程
65
69
  Processes: 处理中
70
+ Name: 名称
66
71
  Thread: 线程
67
72
  Threads: 线程
68
- Jobs: 作业
73
+ Jobs: 任务
74
+ Paused: 已暫停
75
+ Stop: 強制暫停
76
+ Quiet: 暫停
77
+ StopAll: 全部強制暫停
78
+ QuietAll: 全部暫停
79
+ PollingInterval: 輪詢週期
80
+ Plugins: 套件
81
+ NotYetEnqueued: 尚未進入佇列
82
+ CreatedAt: 建立時間
83
+ BackToApp: 回首頁
84
+ Latency: 延時
85
+ Pause: 暫停
86
+ Unpause: 取消暂停
87
+ Metrics: 指标
88
+ NoDataFound: 无数据
89
+ TotalExecutionTime: 总执行时间
90
+ AvgExecutionTime: 平均执行时间
91
+ Context: 上下文
92
+ Bucket: 桶
93
+ NoJobMetricsFound: 无任务相关指标数据
@@ -7,6 +7,7 @@ zh-tw: # <---- change this to your locale code
7
7
  Realtime: 即時
8
8
  History: 歷史資料
9
9
  Busy: 忙碌
10
+ Utilization: 使用率
10
11
  Processed: 已處理
11
12
  Failed: 已失敗
12
13
  Scheduled: 已排程
@@ -25,26 +26,28 @@ zh-tw: # <---- change this to your locale code
25
26
  CurrentMessagesInQueue: 目前在<span class='title'>%{queue}</span>的工作
26
27
  Delete: 刪除
27
28
  AddToQueue: 增加至佇列
28
- AreYouSureDeleteJob: 你確定要刪除這個工作嗎?
29
- AreYouSureDeleteQueue: 你確定要刪除%{queue}這個佇列?
29
+ AreYouSureDeleteJob: 確定要刪除這個工作嗎?
30
+ AreYouSureDeleteQueue: 確定要刪除%{queue}佇列?這會刪除佇列裡的所有工作,佇列將會在有新工作時重新出現。
30
31
  Queues: 佇列
31
32
  Size: 容量
32
33
  Actions: 動作
33
34
  NextRetry: 下次重試
34
35
  RetryCount: 重試次數
35
36
  RetryNow: 馬上重試
37
+ Kill: 取消
36
38
  LastRetry: 最後一次重試
37
39
  OriginallyFailed: 原本已失敗
38
40
  AreYouSure: 你確定?
39
- DeleteAll: 刪除全部
40
- RetryAll: 重試全部
41
- NoRetriesFound: 沒有發現可重試
41
+ DeleteAll: 全部刪除
42
+ RetryAll: 全部重試
43
+ KillAll: 全部取消
44
+ NoRetriesFound: 找無可重試的工作
42
45
  Error: 錯誤
43
46
  ErrorClass: 錯誤類別
44
47
  ErrorMessage: 錯誤訊息
45
- ErrorBacktrace: 錯誤的回調追踨
48
+ ErrorBacktrace: 詳細錯誤訊息
46
49
  GoBack: ← 返回
47
- NoScheduledFound: 沒有發現已排程的工作
50
+ NoScheduledFound: 找無已排程的工作
48
51
  When: 當
49
52
  ScheduledJobs: 已排程的工作
50
53
  idle: 閒置
@@ -62,7 +65,29 @@ zh-tw: # <---- change this to your locale code
62
65
  DeadJobs: 停滯工作
63
66
  NoDeadJobsFound: 沒有發現任何停滯的工作
64
67
  Dead: 停滯
68
+ Process: 程序
65
69
  Processes: 處理中
70
+ Name: 名稱
66
71
  Thread: 執行緒
67
72
  Threads: 執行緒
68
73
  Jobs: 工作
74
+ Paused: 已暫停
75
+ Stop: 強制暫停
76
+ Quiet: 暫停
77
+ StopAll: 全部強制暫停
78
+ QuietAll: 全部暫停
79
+ PollingInterval: 輪詢週期
80
+ Plugins: 套件
81
+ NotYetEnqueued: 尚未進入佇列
82
+ CreatedAt: 建立時間
83
+ BackToApp: 回首頁
84
+ Latency: 延時
85
+ Pause: 暫停
86
+ Unpause: 取消暫停
87
+ Metrics: 計量
88
+ NoDataFound: 找無資料
89
+ TotalExecutionTime: 總執行時間
90
+ AvgExecutionTime: 平均執行時間
91
+ Context: 上下文
92
+ Bucket: 桶
93
+ NoJobMetricsFound: 找無工作相關計量資料
data/web/views/_nav.erb CHANGED
@@ -1,7 +1,7 @@
1
1
  <div class="navbar navbar-default navbar-fixed-top">
2
2
  <div class="container-fluid">
3
3
  <div class="navbar-header" data-navbar="static">
4
- <button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#navbar-menu">
4
+ <button type="button" class="navbar-toggle collapsed" data-toggle="navbar-menu" data-target="#navbar-menu">
5
5
  <span class="icon-bar"></span>
6
6
  <span class="icon-bar"></span>
7
7
  <span class="icon-bar"></span>