Queues with plugins - Enable adding queues with plugins, Management UI

This commit is contained in:
Iliia Khaprov 2025-02-07 10:23:46 +01:00
parent 5fd3bddcfe
commit de17a77df4
No known key found for this signature in database
GPG Key ID: 4DCFF8F358E49AED
22 changed files with 662 additions and 419 deletions

View File

@ -223,7 +223,7 @@ var HELP = {
'Optional replacement routing key to use when a message is dead-lettered. If this is not set, the message\'s original routing key will be used.<br/>(Sets the "<a target="_blank" href="https://rabbitmq.com/dlx.html">x-dead-letter-routing-key</a>" argument.)',
'queue-dead-letter-strategy':
'Valid values are <code>at-most-once</code> or <code>at-least-once</code>. It defaults to <code>at-most-once</code>. This setting is understood only by quorum queues. If <code>at-least-once</code> is set, <code>Overflow behaviour</code> must be set to <code>reject-publish</code>. Otherwise, dead letter strategy will fall back to <code>at-most-once</code>.',
'Valid values are <code>at-most-once</code> or <code>at-least-once</code>. It defaults to <code>at-most-once</code>. If <code>at-least-once</code> is set, <code>Overflow behaviour</code> must be set to <code>reject-publish</code>. Otherwise, dead letter strategy will fall back to <code>at-most-once</code>.',
'queue-single-active-consumer':
'If set, makes sure only one consumer at a time consumes from the queue and fails over to another registered consumer in case the active one is cancelled or dies.<br/>(Sets the "<a target="_blank" href="https://rabbitmq.com/consumers.html#single-active-consumer">x-single-active-consumer</a>" argument.)',
@ -235,7 +235,10 @@ var HELP = {
'Sets the data retention for stream queues in time units </br>(Y=Years, M=Months, D=Days, h=hours, m=minutes, s=seconds).<br/>E.g. "1h" configures the stream to only keep the last 1 hour of received messages.</br></br>(Sets the x-max-age argument.)',
'queue-overflow':
'Sets the <a target="_blank" href="https://www.rabbitmq.com/maxlength.html#overflow-behaviour">queue overflow behaviour</a>. This determines what happens to messages when the maximum length of a queue is reached. Valid values are <code>drop-head</code>, <code>reject-publish</code> or <code>reject-publish-dlx</code>. The quorum queue type only supports <code>drop-head</code> and <code>reject-publish</code>.',
'Sets the <a target="_blank" href="https://www.rabbitmq.com/maxlength.html#overflow-behaviour">queue overflow behaviour</a>. This determines what happens to messages when the maximum length of a queue is reached. Valid values are <code>drop-head</code>, <code>reject-publish</code> or <code>reject-publish-dlx</code>',
'quorum-queue-overflow':
'Sets the <a target="_blank" href="https://www.rabbitmq.com/maxlength.html#overflow-behaviour">queue overflow behaviour</a>. This determines what happens to messages when the maximum length of a queue is reached. Valid values for quorum queues are <code>drop-head</code> and <code>reject-publish</code>.',
'queue-master-locator':
'Deprecated: please use `queue-leader-locator` instead. <a target="_blank" href="https://www.rabbitmq.com/docs/clustering#replica-placement">Controls which node the queue will be running on.</a>',
@ -887,3 +890,239 @@ var chart_data = {};
var last_page_out_of_range_error = 0;
var oauth;
///////////////////////////////////////////////////////////////////////////
// //
// Queue types //
// //
///////////////////////////////////////////////////////////////////////////
/// this queue types are very well known to the server, at the very least
/// this collection must be validated in terms of matching server queue
/// types registry. I hope I will have time for this.
/// this one defaults to classic, How can a queue be without type?
var QUEUE_TYPE = function (queue) {
if (queue["arguments"]) {
if (queue["arguments"]["x-queue-type"]) {
return QUEUE_TYPE[queue["arguments"]["x-queue-type"]];
} else {
/// I observed that streams do not have
/// (at least always) x-queue-type
/// but all queues seems to be having
/// type field.
/// curiosuly is_[type] functions in main.js
/// rely on x-queue-type. is_stream might be
/// broken here.
if (queue.hasOwnProperty("type")) {
return QUEUE_TYPE[queue.type];
}
else {
return QUEUE_TYPE["classic"];
}
}
} else {
return QUEUE_TYPE["classic"];
}
}
// TODO: while this allows for custom queues
// the proper way is to follow single source of truth
// and generate most of this on the server from queue type metadata
// including replacing tmpl's with data-driven generators
// For example server knows policy_apply_to for each queue
// and it knows what extra agruments each queue type accepts.
// So for the latter case we dont' need a template that lists
// queue args. We need iterator over server-supplied object.
QUEUE_TYPE["default"] = {
label: "Default",
params: {},
policy_apply_to: "classic_queue",
actions: {
get_message: true,
purge: true
},
tmpl: {
"arguments" : "classic-queue-arguments",
// TODO: this must be generated from js objects of course.
// and then those objects must be rendered by the server
"user_policy_arguments": "classic-queue-user-policy-arguments",
"operator_policy_arguments": "classic-queue-operator-policy-arguments",
"list" : "classic-queue-list",
"stats" : "classic-queue-stats",
"node_details" : "classic-queue-node-details"
}
};
QUEUE_TYPE["classic"] = {
label: "Classic",
params: {},
policy_apply_to: "classic_queue",
actions: {
get_message: true,
purge: true
},
tmpl: {
"arguments" : "classic-queue-arguments",
"user_policy_arguments": "classic-queue-user-policy-arguments",
"operator_policy_arguments": "classic-queue-operator-policy-arguments",
"list" : "classic-queue-list",
"stats" : "classic-queue-stats",
"node_details" : "classic-queue-node-details"
}
};
QUEUE_TYPE["quorum"] = {
label: "Quorum",
params: {
'durable': true,
'auto_delete': false
},
policy_apply_to: "quorum_queues",
actions: {
get_message: true,
purge: true
},
tmpl: {
"arguments" : "quorum-queue-arguments",
"user_policy_arguments": "quorum-queue-user-policy-arguments",
"operator_policy_arguments": "quorum-queue-operator-policy-arguments",
"list" : "quorum-queue-list",
"stats": "quorum-queue-stats",
"node_details" : "quorum-queue-node-details"
}
};
QUEUE_TYPE["stream"] = {
label: "Stream",
params: {
'durable': true,
'auto_delete': false
},
policy_apply_to: "streams",
actions: {
get_message: false,
purge: false
},
tmpl: {
"arguments" : "stream-queue-arguments",
"user_policy_arguments": "quorum-queue-user-policy-arguments",
"operator_policy_arguments": "stream-queue-operator-policy-arguments",
"list" : "stream-queue-list",
"stats" : "stream-queue-stats",
"node_details" : "stream-queue-node-details"
}
};
// here I'll shortcut for now and let it be like that
// other queue types can inject themlves where they want.
// since the 'sections' object will likely keep key insertion
// order custom keys for queue type will be coming last.
// maybe add helper functions?
var MEMORY_STATISTICS = {
sections: {'queue_procs' : ['classic', 'Classic queues'],
'quorum_queue_procs' : ['quorum', 'Quorum queues'],
'quorum_queue_dlx_procs' : ['quorum', 'Dead letter workers'],
'stream_queue_procs' : ['stream', 'Stream queues'],
'stream_queue_replica_reader_procs' : ['stream', 'Stream queues (replica reader)'],
'stream_queue_coordinator_procs' : ['stream', 'Stream queues (coordinator)'],
'binary' : ['binary', 'Binaries'],
'connection_readers' : ['conn', 'Connection readers'],
'connection_writers' : ['conn', 'Connection writers'],
'connection_channels' : ['conn', 'Connection channels'],
'connection_other' : ['conn', 'Connections (other)'],
'mnesia' : ['table', 'Mnesia'],
'msg_index' : ['table', 'Message store index'],
'mgmt_db' : ['table', 'Management database'],
'quorum_ets' : ['table', 'Quorum queue ETS tables'],
'other_ets' : ['table', 'Other ETS tables'],
'plugins' : ['proc', 'Plugins'],
'other_proc' : ['proc', 'Other process memory'],
'code' : ['system', 'Code'],
'atom' : ['system', 'Atoms'],
'other_system' : ['system', 'Other system'],
'allocated_unused' : ['unused', 'Allocated unused'],
'reserved_unallocated': ['unused', 'Unallocated reserved by the OS']},
keys: [[{name: 'Classic Queues', colour: 'classic',
keys: [['queue_procs', 'queues']]},
{name: 'Quorum Queues', colour: 'quorum',
keys: [['quorum_queue_procs','quorum'],
['quorum_queue_dlx_procs', 'dead letter workers']]},
{name: 'Streams', colour: 'stream',
keys: [['stream_queue_procs', 'stream'],
['stream_queue_replica_reader_procs', 'stream replica reader'],
['stream_queue_coordinator_procs', 'stream coordinator']]},
{name: 'Binaries', colour: 'binary',
keys: [['binary', '']]}],
[{name: 'Connections', colour: 'conn',
keys: [['connection_readers', 'readers'],
['connection_writers', 'writers'],
['connection_channels', 'channels'],
['connection_other', 'other']]}],
[{name: 'Tables', colour: 'table',
keys: [['mnesia', 'internal database tables'],
['msg_index', 'message store index'],
['mgmt_db', 'management database'],
['quorum_ets', 'quorum queue tables'],
['other_ets', 'other']]}],
[{name: 'Processes', colour: 'proc',
keys: [['plugins', 'plugins'],
['metadata_store', 'metadata store'],
['other_proc', 'other']]},
{name: 'System', colour: 'system',
keys: [['code', 'code'],
['atom', 'atoms'],
['other_system', 'other']
]}],
[{name: 'Preallocated memory', colour: 'unused',
keys: [['allocated_unused', 'preallocated by runtime, unused'],
['reserved_unallocated', 'unallocated, reserved by the OS']]}]]
}
var BINARY_STATISTICS = {
sections: {'queue_procs' : ['classic', 'Classic queues'],
'quorum_queue_procs' : ['quorum', 'Quorum queues'],
'quorum_queue_dlx_procs' : ['quorum', 'Dead letter workers'],
'stream_queue_procs' : ['stream', 'Stream queues'],
'stream_queue_replica_reader_procs' : ['stream', 'Stream queues (replica reader)'],
'stream_queue_coordinator_procs' : ['stream', 'Stream queues (coordinator)'],
'connection_readers' : ['conn', 'Connection readers'],
'connection_writers' : ['conn', 'Connection writers'],
'connection_channels' : ['conn', 'Connection channels'],
'connection_other' : ['conn', 'Connections (other)'],
'msg_index' : ['table', 'Message store index'],
'mgmt_db' : ['table', 'Management database'],
'plugins' : ['proc', 'Plugins'],
'metadata_store' : ['metadata_store', 'Metadata store'],
'other' : ['system', 'Other binary references']},
key: [[{name: 'Classic Queues', colour: 'classic',
keys: [['queue_procs', 'queues']]},
{name: 'Quorum Queues', colour: 'quorum',
keys: [['quorum_queue_procs', 'quorum'],
['quorum_queue_dlx_procs', 'dead letter workers']]},
{name: 'Streams', colour: 'stream',
keys: [['stream_queue_procs', 'stream'],
['stream_queue_replica_reader_procs', 'stream replica reader'],
['stream_queue_coordinator_procs', 'stream coordinator']]}],
[{name: 'Connections', colour: 'conn',
keys: [['connection_readers', 'readers'],
['connection_writers', 'writers'],
['connection_channels', 'channels'],
['connection_other', 'other']]}],
[{name: 'Tables', colour: 'table',
keys: [['msg_index', 'message store index'],
['mgmt_db', 'management database']]}],
[{name: 'Processes', colour: 'proc',
keys: [['plugins', 'plugins'],
['metadata_store', 'metadata store']]},
{name: 'System', colour: 'system',
keys: [['other', 'other']]}]]
};

View File

@ -1578,11 +1578,8 @@ function collapse_multifields(params0) {
if (queue_type != 'default') {
params['arguments']['x-queue-type'] = queue_type;
}
if (queue_type == 'quorum' ||
queue_type == 'stream') {
params['durable'] = true;
params['auto_delete'] = false;
}
params = Object.assign(params, QUEUE_TYPE[queue_type].params)
}
return params;
}

View File

@ -5,56 +5,14 @@
Binary statistics not available.
</p>
<% } else { %>
<%
var sections = {'queue_procs' : ['classic', 'Classic queues'],
'quorum_queue_procs' : ['quorum', 'Quorum queues'],
'quorum_queue_dlx_procs' : ['quorum', 'Dead letter workers'],
'stream_queue_procs' : ['stream', 'Stream queues'],
'stream_queue_replica_reader_procs' : ['stream', 'Stream queues (replica reader)'],
'stream_queue_coordinator_procs' : ['stream', 'Stream queues (coordinator)'],
'connection_readers' : ['conn', 'Connection readers'],
'connection_writers' : ['conn', 'Connection writers'],
'connection_channels' : ['conn', 'Connection channels'],
'connection_other' : ['conn', 'Connections (other)'],
'msg_index' : ['table', 'Message store index'],
'mgmt_db' : ['table', 'Management database'],
'plugins' : ['proc', 'Plugins'],
'metadata_store' : ['metadata_store', 'Metadata store'],
'other' : ['system', 'Other binary references']};
<%
var total_out = [];
%>
<%= format('memory-bar', {sections: sections, memory: binary, total_out: total_out}) %>
<span class="clear">&nbsp;</span>
<div class="box">
<%
var key = [[{name: 'Classic Queues', colour: 'classic',
keys: [['queue_procs', 'queues']]},
{name: 'Quorum Queues', colour: 'quorum',
keys: [['quorum_queue_procs', 'quorum'],
['quorum_queue_dlx_procs', 'dead letter workers']]},
{name: 'Streams', colour: 'stream',
keys: [['stream_queue_procs', 'stream'],
['stream_queue_replica_reader_procs', 'stream replica reader'],
['stream_queue_coordinator_procs', 'stream coordinator']]}],
[{name: 'Connections', colour: 'conn',
keys: [['connection_readers', 'readers'],
['connection_writers', 'writers'],
['connection_channels', 'channels'],
['connection_other', 'other']]}],
[{name: 'Tables', colour: 'table',
keys: [['msg_index', 'message store index'],
['mgmt_db', 'management database']]}],
[{name: 'Processes', colour: 'proc',
keys: [['plugins', 'plugins'],
['metadata_store', 'metadata store']]},
{name: 'System', colour: 'system',
keys: [['other', 'other']]}]];
%>
<%= format('memory-table', {key: key, memory: binary}) %>
</div>
%>
<%= format('memory-bar', {sections: BINARY_STATISTICS.sections, memory: binary, total_out: total_out}) %>
<span class="clear">&nbsp;</span>
<div class="box">
<%= format('memory-table', {key: BINARY_STATISTICS. key, memory: binary}) %>
</div>
<div class="memory-info">
Last updated: <b><%= fmt_date(new Date()) %></b>.<br/>

View File

@ -0,0 +1,10 @@
<span class="argument-link" field="arguments" key="x-expires" type="number">Auto expire</span> <span class="help" id="queue-expires"></span> |
<span class="argument-link" field="arguments" key="x-message-ttl" type="number">Message TTL</span> <span class="help" id="queue-message-ttl"></span> |
<span class="argument-link" field="arguments" key="x-overflow" type="string">Overflow behaviour</span> <span class="help" id="queue-overflow"></span><br/>
<span class="argument-link" field="arguments" key="x-single-active-consumer" type="boolean">Single active consumer</span> <span class="help" id="queue-single-active-consumer"></span> |
<span class="argument-link" field="arguments" key="x-dead-letter-exchange" type="string">Dead letter exchange</span> <span class="help" id="queue-dead-letter-exchange"></span> |
<span class="argument-link" field="arguments" key="x-dead-letter-routing-key" type="string">Dead letter routing key</span> <span class="help" id="queue-dead-letter-routing-key"></span><br/>
<span class="argument-link" field="arguments" key="x-max-length" type="number">Max length</span> <span class="help" id="queue-max-length"></span> |
<span class="argument-link" field="arguments" key="x-max-length-bytes" type="number">Max length bytes</span> <span class="help" id="queue-max-length-bytes"></span>
| <span class="argument-link" field="arguments" key="x-max-priority" type="number">Maximum priority</span> <span class="help" id="queue-max-priority"></span>
| <span class="argument-link" field="arguments" key="x-queue-leader-locator" type="string">Leader locator</span><span class="help" id="queue-leader-locator"></span>

View File

@ -0,0 +1,4 @@
<tr>
<th>Node</th>
<td><%= fmt_node(queue.node) %></td>
</tr>

View File

@ -0,0 +1,11 @@
<tr>
<td>Queues [Classic]</td>
<td>
<span class="argument-link" field="definitionop" key="expires" type="number">Auto expire</span> |
<span class="argument-link" field="definitionop" key="max-length" type="number">Max length</span> |
<span class="argument-link" field="definitionop" key="max-length-bytes" type="number">Max length bytes</span> |
<span class="argument-link" field="definitionop" key="message-ttl" type="number">Message TTL</span> |
<span class="help" id="queue-message-ttl"></span> |
<span class="argument-link" field="definitionop" key="overflow" type="string">Length limit overflow behaviour</span> <span class="help" id="queue-overflow"></span> </br>
</td>
</tr>

View File

@ -0,0 +1,94 @@
<table class="facts facts-l">
<tr>
<th>State</th>
<td><%= fmt_object_state(queue) %></td>
</tr>
<% if(queue.consumers) { %>
<tr>
<th>Consumers</th>
<td><%= fmt_string(queue.consumers) %></td>
</tr>
<% } else if(queue.hasOwnProperty('consumer_details')) { %>
<tr>
<th>Consumers</th>
<td><%= fmt_string(queue.consumer_details.length) %></td>
</tr>
<% } %>
<tr>
<th>Consumer capacity <span class="help" id="queue-consumer-capacity"></th>
<td><%= fmt_percent(queue.consumer_capacity) %></td>
</tr>
<% if(queue.hasOwnProperty('publishers')) { %>
<tr>
<th>Publishers</th>
<td><%= fmt_string(queue.publishers) %></td>
</tr>
<% } %>
</table>
<table class="facts">
<tr>
<td></td>
<th class="horizontal">Total</th>
<th class="horizontal">Ready</th>
<th class="horizontal">Unacked</th>
<th class="horizontal">In memory</th>
<th class="horizontal">Persistent</th>
<th class="horizontal">Transient, Paged Out</th>
</tr>
<tr>
<th>
Messages
<span class="help" id="queue-messages"></span>
</th>
<td class="r">
<%= fmt_num_thousands(queue.messages) %>
</td>
<td class="r">
<%= fmt_num_thousands(queue.messages_ready) %>
</td>
<td class="r">
<%= fmt_num_thousands(queue.messages_unacknowledged) %>
</td>
<td class="r">
<%= fmt_num_thousands(queue.messages_ram) %>
</td>
<td class="r">
<%= fmt_num_thousands(queue.messages_persistent) %>
</td>
<td class="r">
<%= fmt_num_thousands(queue.messages_paged_out) %>
</td>
</tr>
<tr>
<th>
Message body bytes
<span class="help" id="queue-message-body-bytes"></span>
</th>
<td class="r">
<%= fmt_bytes(queue.message_bytes) %>
</td>
<td class="r">
<%= fmt_bytes(queue.message_bytes_ready) %>
</td>
<td class="r">
<%= fmt_bytes(queue.message_bytes_unacknowledged) %>
</td>
<td class="r">
<%= fmt_bytes(queue.message_bytes_ram) %>
</td>
<td class="r">
<%= fmt_bytes(queue.message_bytes_persistent) %>
</td>
<td class="r">
<%= fmt_bytes(queue.message_bytes_paged_out) %>
</td>
</tr>
<tr>
<th>
Process memory
<span class="help" id="queue-process-memory"></span>
</th>
<td class="r"><%= fmt_bytes(queue.memory) %></td>
</tr>
</table>

View File

@ -5,75 +5,10 @@
Memory statistics not available.
</p>
<% } else { %>
<%
var sections = {'queue_procs' : ['classic', 'Classic queues'],
'quorum_queue_procs' : ['quorum', 'Quorum queues'],
'quorum_queue_dlx_procs' : ['quorum', 'Dead letter workers'],
'stream_queue_procs' : ['stream', 'Stream queues'],
'stream_queue_replica_reader_procs' : ['stream', 'Stream queues (replica reader)'],
'stream_queue_coordinator_procs' : ['stream', 'Stream queues (coordinator)'],
'binary' : ['binary', 'Binaries'],
'connection_readers' : ['conn', 'Connection readers'],
'connection_writers' : ['conn', 'Connection writers'],
'connection_channels' : ['conn', 'Connection channels'],
'connection_other' : ['conn', 'Connections (other)'],
'mnesia' : ['table', 'Mnesia'],
'msg_index' : ['table', 'Message store index'],
'mgmt_db' : ['table', 'Management database'],
'quorum_ets' : ['table', 'Quorum queue ETS tables'],
'other_ets' : ['table', 'Other ETS tables'],
'plugins' : ['proc', 'Plugins'],
'other_proc' : ['proc', 'Other process memory'],
'code' : ['system', 'Code'],
'atom' : ['system', 'Atoms'],
'other_system' : ['system', 'Other system'],
'allocated_unused' : ['unused', 'Allocated unused'],
'reserved_unallocated': ['unused', 'Unallocated reserved by the OS']};
%>
<%= format('memory-bar', {sections: sections, memory: memory, total_out: []}) %>
<%= format('memory-bar', {sections: MEMORY_STATISTICS.sections, memory: memory, total_out: []}) %>
<span class="clear">&nbsp;</span>
<div class="box">
<%
var key = [[{name: 'Classic Queues', colour: 'classic',
keys: [['queue_procs', 'queues']]},
{name: 'Quorum Queues', colour: 'quorum',
keys: [['quorum_queue_procs','quorum'],
['quorum_queue_dlx_procs', 'dead letter workers']]},
{name: 'Streams', colour: 'stream',
keys: [['stream_queue_procs', 'stream'],
['stream_queue_replica_reader_procs', 'stream replica reader'],
['stream_queue_coordinator_procs', 'stream coordinator']]},
{name: 'Binaries', colour: 'binary',
keys: [['binary', '']]}],
[{name: 'Connections', colour: 'conn',
keys: [['connection_readers', 'readers'],
['connection_writers', 'writers'],
['connection_channels', 'channels'],
['connection_other', 'other']]}],
[{name: 'Tables', colour: 'table',
keys: [['mnesia', 'internal database tables'],
['msg_index', 'message store index'],
['mgmt_db', 'management database'],
['quorum_ets', 'quorum queue tables'],
['other_ets', 'other']]}],
[{name: 'Processes', colour: 'proc',
keys: [['plugins', 'plugins'],
['metadata_store', 'metadata store'],
['other_proc', 'other']]},
{name: 'System', colour: 'system',
keys: [['code', 'code'],
['atom', 'atoms'],
['other_system', 'other']
]}],
[{name: 'Preallocated memory', colour: 'unused',
keys: [['allocated_unused', 'preallocated by runtime, unused'],
['reserved_unallocated', 'unallocated, reserved by the OS']]}]];
%>
<%= format('memory-table', {key: key, memory: memory}) %>
<%= format('memory-table', {key: MEMORY_STATISTICS.keys, memory: memory}) %>
</div>
<div class="memory-info">

View File

@ -83,9 +83,11 @@
<option value="all">Exchanges and queues</option>
<option value="exchanges">Exchanges</option>
<option value="queues">Queues</option>
<option value="classic_queues">Classic Queues</option>
<option value="quorum_queues">Quorum Queues</option>
<option value="streams">Streams</option>
<% for (const [typename, type_config] of Object.entries(QUEUE_TYPE)) { %>
<% if (typename != "default") { %>
<option value="<%= type_config.policy_apply_to %>"><%= type_config.label %> Queues</option>
<% } %>
<% } %>
</select>
</td>
</tr>
@ -111,15 +113,11 @@
<span class="argument-link" field="definition" key="consumer-timeout" type="number">Consumer Timeout</span><span class="help" id="queue-consumer-timeout"></span> |
<span class="argument-link" field="definition" key="queue-leader-locator" type="string">Leader locator</span><span class="help" id="queue-leader-locator"></span></br>
</td>
<tr>
<td>Queues [Quorum]</td>
<td>
<span class="argument-link" field="definition" key="delivery-limit" type="number">Delivery limit</span>
<span class="help" id="delivery-limit"></span> |
<span class="argument-link" field="definition" key="dead-letter-strategy" type="string">Dead letter strategy</span>
<span class="help" id="queue-dead-letter-strategy"></span> |
</td>
</tr>
<% for (const [typename, type_config] of Object.entries(QUEUE_TYPE)) { %>
<% if (typename != "default") { %>
<%= format(type_config.tmpl.user_policy_arguments, {}) %>
<% } %>
<% } %>
<tr>
<td>Streams</td>
<td>
@ -246,9 +244,11 @@
<td>
<select name="apply-to">
<option value="queues">Queues</option>
<option value="classic_queues">Classic Queues</option>
<option value="quorum_queues">Quorum Queues</option>
<option value="streams">Streams</option>
<% for (const [typename, type_config] of Object.entries(QUEUE_TYPE)) { %>
<% if (typename != "default") { %>
<option value="<%= type_config.policy_apply_to %>"><%= type_config.label %> Queues</option>
<% } %>
<% } %>
</select>
</td>
</tr>
@ -261,39 +261,11 @@
<td>
<div class="multifield" id="definitionop"></div>
<table class="argument-links">
<tr>
<td>Queues [Classic]</td>
<td>
<span class="argument-link" field="definitionop" key="expires" type="number">Auto expire</span> |
<span class="argument-link" field="definitionop" key="max-length" type="number">Max length</span> |
<span class="argument-link" field="definitionop" key="max-length-bytes" type="number">Max length bytes</span> |
<span class="argument-link" field="definitionop" key="message-ttl" type="number">Message TTL</span> |
<span class="help" id="queue-message-ttl"></span> |
<span class="argument-link" field="definitionop" key="overflow" type="string">Length limit overflow behaviour</span> <span class="help" id="queue-overflow"></span> </br>
</td>
</tr>
<tr>
<td>Queues [Quorum]</td>
<td>
<span class="argument-link" field="definitionop" key="delivery-limit" type="number">Delivery limit</span>
<span class="help" id="delivery-limit"></span> |
<span class="argument-link" field="definitionop" key="expires" type="number">Auto expire</span> |
<span class="argument-link" field="definitionop" key="max-in-memory-bytes" type="number">Max in-memory bytes</span> |
<span class="argument-link" field="definitionop" key="max-in-memory-length" type="number">Max in-memory length</span> <br>
<span class="argument-link" field="definitionop" key="max-length" type="number">Max length</span> |
<span class="argument-link" field="definitionop" key="max-length-bytes" type="number">Max length bytes</span> |
<span class="argument-link" field="definitionop" key="message-ttl" type="number">Message TTL</span>
<span class="help" id="queue-message-ttl"></span> |
<span class="argument-link" field="definitionop" key="target-group-size" type="number">Target group size</span> |
<span class="argument-link" field="definitionop" key="overflow" type="string">Length limit overflow behaviour</span> <span class="help" id="queue-overflow"></span> </br>
</td>
</tr>
<tr>
<td>Queues [Streams]</td>
<td>
<span class="argument-link" field="definitionop" key="max-length-bytes" type="number">Max length bytes</span>
</td>
</tr>
<% for (const [typename, type_config] of Object.entries(QUEUE_TYPE)) { %>
<% if (typename != "default") { %>
<%= format(type_config.tmpl.operator_policy_arguments, {}) %>
<% } %>
<% } %>
</table>
</td>
<td class="t"><span class="mand">*</span></td>

View File

@ -37,212 +37,12 @@
</tr>
<% } %>
<% if (nodes_interesting) { %>
<tr>
<% if (is_quorum(queue) || is_stream(queue)) { %>
<th>Leader</th>
<% } else { %>
<th>Node</th>
<% } %>
<% if (queue.leader) { %>
<td><%= fmt_node(queue.leader) %></td>
<% } else { %>
<td><%= fmt_node(queue.node) %></td>
<% } %>
</tr>
<% if (is_quorum(queue) || is_stream(queue)) { %>
<tr>
<th>Online</th>
<td>
<%
for (var i in queue.online) {
%>
<%= fmt_node(queue.online[i]) %>
<br/>
<% } %>
</td>
</tr>
<th>Members</th>
<td>
<%
for (var i in queue.members) {
%>
<%= fmt_node(queue.members[i]) %>
<br/>
<% } %>
</td>
</tr>
<% } %>
<%= format(QUEUE_TYPE(queue).tmpl.node_details, {queue: queue}) %>
<% } %>
</table>
<% if(!disable_stats) { %>
<table class="facts facts-l">
<tr>
<th>State</th>
<td><%= fmt_object_state(queue) %></td>
</tr>
<% if(queue.consumers) { %>
<tr>
<th>Consumers</th>
<td><%= fmt_string(queue.consumers) %></td>
</tr>
<% } else if(queue.hasOwnProperty('consumer_details')) { %>
<tr>
<th>Consumers</th>
<td><%= fmt_string(queue.consumer_details.length) %></td>
</tr>
<% } %>
<% if (is_classic(queue)) { %>
<tr>
<th>Consumer capacity <span class="help" id="queue-consumer-capacity"></th>
<td><%= fmt_percent(queue.consumer_capacity) %></td>
</tr>
<% } %>
<% if(queue.hasOwnProperty('publishers')) { %>
<tr>
<th>Publishers</th>
<td><%= fmt_string(queue.publishers) %></td>
</tr>
<% } %>
<% if (is_quorum(queue)) { %>
<tr>
<th>Open files</th>
<td><%= fmt_table_short(queue.open_files) %></td>
</tr>
<% if (queue.hasOwnProperty('delivery_limit')) { %>
<tr>
<th>Delivery limit <span class="help" id="queue-delivery-limit"></th>
<td><%= fmt_string(queue.delivery_limit) %></td>
</tr>
<% } %>
<% } %>
<% if (is_stream(queue)) { %>
<tr>
<th>Readers</th>
<td><%= fmt_table_short(queue.readers) %></td>
</tr>
<tr>
<th>Segments</th>
<td><%= fmt_string(queue.segments) %></td>
</tr>
<% } %>
</table>
<table class="facts">
<tr>
<td></td>
<th class="horizontal">Total</th>
<% if (!is_stream(queue)) { %>
<th class="horizontal">Ready</th>
<th class="horizontal">Unacked</th>
<% } %>
<% if (is_quorum(queue)) { %>
<th class="horizontal">High priority</th>
<th class="horizontal">Normal priority</th>
<th class="horizontal">Returned</th>
<th class="horizontal">Dead-lettered
<span class="help" id="queue-dead-lettered"></span>
</th>
<% } %>
<% if (is_classic(queue)) { %>
<th class="horizontal">In memory</th>
<th class="horizontal">Persistent</th>
<th class="horizontal">Transient</th>
<% } %>
</tr>
<tr>
<th>
Messages
<% if (is_stream(queue)) { %>
<span class="help" id="queue-messages-stream"></span>
<% } else { %>
<span class="help" id="queue-messages"></span>
<% } %>
</th>
<td class="r">
<%= fmt_num_thousands(queue.messages) %>
</td>
<% if (!is_stream(queue)) { %>
<td class="r">
<%= fmt_num_thousands(queue.messages_ready) %>
</td>
<td class="r">
<%= fmt_num_thousands(queue.messages_unacknowledged) %>
</td>
<% } %>
<% if (is_quorum(queue)) { %>
<td class="r">
<%= fmt_num_thousands(queue.messages_ready_high) %>
</td>
<td class="r">
<%= fmt_num_thousands(queue.messages_ready_normal) %>
</td>
<td class="r">
<%= fmt_num_thousands(queue.messages_ready_returned) %>
</td>
<td class="r">
<%= fmt_num_thousands(queue.messages_dlx) %>
</td>
<% } %>
<% if (is_classic(queue)) { %>
<td class="r">
<%= fmt_num_thousands(queue.messages_ram) %>
</td>
<td class="r">
<%= fmt_num_thousands(queue.messages_persistent) %>
</td>
<td class="r">
<%= fmt_num_thousands(queue.messages_paged_out) %>
</td>
<% } %>
</tr>
<tr>
<% if (is_classic(queue) || is_quorum(queue)) { %>
<th>
Message body bytes
<span class="help" id="queue-message-body-bytes"></span>
</th>
<td class="r">
<%= fmt_bytes(queue.message_bytes) %>
</td>
<td class="r">
<%= fmt_bytes(queue.message_bytes_ready) %>
</td>
<td class="r">
<%= fmt_bytes(queue.message_bytes_unacknowledged) %>
</td>
<% } %>
<% if (is_quorum(queue)) { %>
<td class="r">
</td>
<td class="r">
</td>
<td class="r">
</td>
<td class="r">
<%= fmt_bytes(queue.message_bytes_dlx) %>
</td>
<% } %>
<% if (is_classic(queue)) { %>
<td class="r">
<%= fmt_bytes(queue.message_bytes_ram) %>
</td>
<td class="r">
<%= fmt_bytes(queue.message_bytes_persistent) %>
</td>
<td class="r">
<%= fmt_bytes(queue.message_bytes_paged_out) %>
</td>
<% } %>
</tr>
<tr>
<th>
Process memory
<span class="help" id="queue-process-memory"></span>
</th>
<td class="r"><%= fmt_bytes(queue.memory) %></td>
</tr>
</table>
<% if(!disable_stats) { %>
<%= format(QUEUE_TYPE(queue).tmpl.stats, {queue: queue}) %>
<% } %>
</div>
</div>
@ -300,7 +100,7 @@
<%= format('publish', {'mode': 'queue', 'queue': queue}) %>
<% if (!is_stream(queue)) { %>
<% if (QUEUE_TYPE(queue).actions.get_message) { %>
<div class="section-hidden">
<h2>Get messages</h2>
<div class="hider">
@ -409,7 +209,7 @@
</div>
<% } %>
<% if (!is_stream(queue)) { %>
<% if (QUEUE_TYPE(queue).actions.purge) { %>
<div class="section-hidden">
<h2>Purge</h2>
<div class="hider">

View File

@ -246,20 +246,14 @@
<td>
<select name="queuetype" onchange="select_queue_type(queuetype)">
<option value="default">Default for virtual host</option>
<% if (queue_type == "classic") { %>
<option value="classic" selected>Classic</option>
<% for (const [typename, type_config] of Object.entries(QUEUE_TYPE)) { %>
<% if (typename != "default") { %>
<% if (queue_type == typename) { %>
<option value="<%= typename%>" selected><%= type_config["label"]%></option>
<% } else { %>
<option value="classic">Classic</option>
<option value="<%= typename%>"><%= type_config["label"]%></option>
<% } %>
<% if (queue_type == "quorum") { %>
<option value="quorum" selected>Quorum</option>
<% } else { %>
<option value="quorum">Quorum</option>
<% } %>
<% if (queue_type == "stream") { %>
<option value="stream" selected>Stream</option>
<% } else { %>
<option value="stream">Stream</option>
<% } %>
</select>
</td>
@ -313,32 +307,7 @@
<tr>
<td>Add</td>
<td>
<% if (queue_type != "stream") { %>
<span class="argument-link" field="arguments" key="x-expires" type="number">Auto expire</span> <span class="help" id="queue-expires"></span> |
<span class="argument-link" field="arguments" key="x-message-ttl" type="number">Message TTL</span> <span class="help" id="queue-message-ttl"></span> |
<span class="argument-link" field="arguments" key="x-overflow" type="string">Overflow behaviour</span> <span class="help" id="queue-overflow"></span><br/>
<span class="argument-link" field="arguments" key="x-single-active-consumer" type="boolean">Single active consumer</span> <span class="help" id="queue-single-active-consumer"></span> |
<span class="argument-link" field="arguments" key="x-dead-letter-exchange" type="string">Dead letter exchange</span> <span class="help" id="queue-dead-letter-exchange"></span> |
<span class="argument-link" field="arguments" key="x-dead-letter-routing-key" type="string">Dead letter routing key</span> <span class="help" id="queue-dead-letter-routing-key"></span><br/>
<span class="argument-link" field="arguments" key="x-max-length" type="number">Max length</span> <span class="help" id="queue-max-length"></span> |
<% } %>
<span class="argument-link" field="arguments" key="x-max-length-bytes" type="number">Max length bytes</span> <span class="help" id="queue-max-length-bytes"></span>
<% if (queue_type == "classic") { %>
| <span class="argument-link" field="arguments" key="x-max-priority" type="number">Maximum priority</span> <span class="help" id="queue-max-priority"></span>
<% } %>
<% if (queue_type == "quorum") { %>
| <span class="argument-link" field="arguments" key="x-delivery-limit" type="number">Delivery limit</span><span class="help" id="delivery-limit"></span>
| <span class="argument-link" field="arguments" key="x-quorum-initial-group-size" type="number">Initial cluster size</span><span class="help" id="queue-initial-cluster-size"></span><br/>
<span class="argument-link" field="arguments" key="x-quorum-target-group-size" type="number">Target cluster size</span><span class="help" id="qourum-queue-target-group-size"></span>
| <span class="argument-link" field="arguments" key="x-dead-letter-strategy" type="string">Dead letter strategy</span><span class="help" id="queue-dead-letter-strategy"></span>
<% } %>
<% if (queue_type == "stream") { %>
| <span class="argument-link" field="arguments" key="x-max-age" type="string">Max time retention</span><span class="help" id="queue-max-age"></span>
| <span class="argument-link" field="arguments" key="x-stream-max-segment-size-bytes" type="number">Max segment size in bytes</span><span class="help" id="queue-stream-max-segment-size-bytes"></span></br>
<span class="argument-link" field="arguments" key="x-stream-filter-size-bytes" type="number">Filter size (per chunk) in bytes</span><span class="help" id="queue-stream-filter-size-bytes"></span>
| <span class="argument-link" field="arguments" key="x-initial-cluster-size" type="number">Initial cluster size</span><span class="help" id="queue-initial-cluster-size"></span>
<% } %>
| <span class="argument-link" field="arguments" key="x-queue-leader-locator" type="string">Leader locator</span><span class="help" id="queue-leader-locator"></span>
<%= format(QUEUE_TYPE[queue_type].tmpl['arguments'], {}) %>
</td>
</tr>
</table>

View File

@ -0,0 +1,13 @@
<span class="argument-link" field="arguments" key="x-expires" type="number">Auto expire</span> <span class="help" id="queue-expires"></span> |
<span class="argument-link" field="arguments" key="x-message-ttl" type="number">Message TTL</span> <span class="help" id="queue-message-ttl"></span> |
<span class="argument-link" field="arguments" key="x-overflow" type="string">Overflow behaviour</span> <span class="help" id="quorum-queue-overflow"></span><br/>
<span class="argument-link" field="arguments" key="x-single-active-consumer" type="boolean">Single active consumer</span> <span class="help" id="queue-single-active-consumer"></span> |
<span class="argument-link" field="arguments" key="x-dead-letter-exchange" type="string">Dead letter exchange</span> <span class="help" id="queue-dead-letter-exchange"></span> |
<span class="argument-link" field="arguments" key="x-dead-letter-routing-key" type="string">Dead letter routing key</span> <span class="help" id="queue-dead-letter-routing-key"></span><br/>
<span class="argument-link" field="arguments" key="x-max-length" type="number">Max length</span> <span class="help" id="queue-max-length"></span> |
<span class="argument-link" field="arguments" key="x-max-length-bytes" type="number">Max length bytes</span> <span class="help" id="queue-max-length-bytes"></span>
| <span class="argument-link" field="arguments" key="x-delivery-limit" type="number">Delivery limit</span><span class="help" id="delivery-limit"></span>
| <span class="argument-link" field="arguments" key="x-quorum-initial-group-size" type="number">Initial cluster size</span><span class="help" id="queue-initial-cluster-size"></span><br/>
<span class="argument-link" field="arguments" key="x-quorum-target-group-size" type="number">Target cluster size</span><span class="help" id="qourum-queue-target-group-size"></span>
| <span class="argument-link" field="arguments" key="x-dead-letter-strategy" type="string">Dead letter strategy</span><span class="help" id="queue-dead-letter-strategy"></span>
| <span class="argument-link" field="arguments" key="x-queue-leader-locator" type="string">Leader locator</span><span class="help" id="queue-leader-locator"></span>

View File

@ -0,0 +1,21 @@
<tr>
<th>Leader</th>
<td><%= fmt_node(queue.leader) %></td>
</tr>
<tr>
<th>Online</th>
<td>
<% for (var i in queue.online) { %>
<%= fmt_node(queue.online[i]) %>
<br/>
<% } %>
</td>
</tr>
<th>Members</th>
<td>
<% for (var i in queue.members) { %>
<%= fmt_node(queue.members[i]) %>
<br/>
<% } %>
</td>
</tr>

View File

@ -0,0 +1,16 @@
<tr>
<td>Queues [Quorum]</td>
<td>
<span class="argument-link" field="definitionop" key="delivery-limit" type="number">Delivery limit</span>
<span class="help" id="delivery-limit"></span> |
<span class="argument-link" field="definitionop" key="expires" type="number">Auto expire</span> |
<span class="argument-link" field="definitionop" key="max-in-memory-bytes" type="number">Max in-memory bytes</span> |
<span class="argument-link" field="definitionop" key="max-in-memory-length" type="number">Max in-memory length</span> <br>
<span class="argument-link" field="definitionop" key="max-length" type="number">Max length</span> |
<span class="argument-link" field="definitionop" key="max-length-bytes" type="number">Max length bytes</span> |
<span class="argument-link" field="definitionop" key="message-ttl" type="number">Message TTL</span>
<span class="help" id="queue-message-ttl"></span> |
<span class="argument-link" field="definitionop" key="target-group-size" type="number">Target group size</span> |
<span class="argument-link" field="definitionop" key="overflow" type="string">Length limit overflow behaviour</span> <span class="help" id="queue-overflow"></span> </br>
</td>
</tr>

View File

@ -0,0 +1,106 @@
<table class="facts facts-l">
<tr>
<th>State</th>
<td><%= fmt_object_state(queue) %></td>
</tr>
<% if(queue.consumers) { %>
<tr>
<th>Consumers</th>
<td><%= fmt_string(queue.consumers) %></td>
</tr>
<% } else if(queue.hasOwnProperty('consumer_details')) { %>
<tr>
<th>Consumers</th>
<td><%= fmt_string(queue.consumer_details.length) %></td>
</tr>
<% } %>
<% if(queue.hasOwnProperty('publishers')) { %>
<tr>
<th>Publishers</th>
<td><%= fmt_string(queue.publishers) %></td>
</tr>
<% } %>
<tr>
<th>Open files</th>
<td><%= fmt_table_short(queue.open_files) %></td>
</tr>
<% if (queue.hasOwnProperty('delivery_limit')) { %>
<tr>
<th>Delivery limit <span class="help" id="queue-delivery-limit"></th>
<td><%= fmt_string(queue.delivery_limit) %></td>
</tr>
<% } %>
</table>
<table class="facts">
<tr>
<td></td>
<th class="horizontal">Total</th>
<th class="horizontal">Ready</th>
<th class="horizontal">Unacked</th>
<th class="horizontal">High priority</th>
<th class="horizontal">Normal priority</th>
<th class="horizontal">Returned</th>
<th class="horizontal">Dead-lettered
<span class="help" id="queue-dead-lettered"></span>
</th>
</tr>
<tr>
<th>
Messages
<span class="help" id="queue-messages"></span>
</th>
<td class="r">
<%= fmt_num_thousands(queue.messages) %>
</td>
<td class="r">
<%= fmt_num_thousands(queue.messages_ready) %>
</td>
<td class="r">
<%= fmt_num_thousands(queue.messages_unacknowledged) %>
</td>
<td class="r">
<%= fmt_num_thousands(queue.messages_ready_high) %>
</td>
<td class="r">
<%= fmt_num_thousands(queue.messages_ready_normal) %>
</td>
<td class="r">
<%= fmt_num_thousands(queue.messages_ready_returned) %>
</td>
<td class="r">
<%= fmt_num_thousands(queue.messages_dlx) %>
</td>
</tr>
<tr>
<th>
Message body bytes
<span class="help" id="queue-message-body-bytes"></span>
</th>
<td class="r">
<%= fmt_bytes(queue.message_bytes) %>
</td>
<td class="r">
<%= fmt_bytes(queue.message_bytes_ready) %>
</td>
<td class="r">
<%= fmt_bytes(queue.message_bytes_unacknowledged) %>
</td>
<td class="r">
</td>
<td class="r">
</td>
<td class="r">
</td>
<td class="r">
<%= fmt_bytes(queue.message_bytes_dlx) %>
</td>
</tr>
<tr>
<th>
Process memory
<span class="help" id="queue-process-memory"></span>
</th>
<td class="r"><%= fmt_bytes(queue.memory) %></td>
</tr>
</table>

View File

@ -0,0 +1,9 @@
<tr>
<td>Queues [Quorum]</td>
<td>
<span class="argument-link" field="definition" key="delivery-limit" type="number">Delivery limit</span>
<span class="help" id="delivery-limit"></span> |
<span class="argument-link" field="definition" key="dead-letter-strategy" type="string">Dead letter strategy</span>
<span class="help" id="queue-dead-letter-strategy"></span> |
</td>
</tr>

View File

@ -0,0 +1,6 @@
<span class="argument-link" field="arguments" key="x-max-length-bytes" type="number">Max length bytes</span> <span class="help" id="queue-max-length-bytes"></span>
| <span class="argument-link" field="arguments" key="x-max-age" type="string">Max time retention</span><span class="help" id="queue-max-age"></span>
| <span class="argument-link" field="arguments" key="x-stream-max-segment-size-bytes" type="number">Max segment size in bytes</span><span class="help" id="queue-stream-max-segment-size-bytes"></span></br>
<span class="argument-link" field="arguments" key="x-stream-filter-size-bytes" type="number">Filter size (per chunk) in bytes</span><span class="help" id="queue-stream-filter-size-bytes"></span>
| <span class="argument-link" field="arguments" key="x-initial-cluster-size" type="number">Initial cluster size</span><span class="help" id="queue-initial-cluster-size"></span>
| <span class="argument-link" field="arguments" key="x-queue-leader-locator" type="string">Leader locator</span><span class="help" id="queue-leader-locator"></span>

View File

@ -0,0 +1,21 @@
<tr>
<th>Leader</th>
<td><%= fmt_node(queue.leader) %></td>
</tr>
<tr>
<th>Online</th>
<td>
<% for (var i in queue.online) { %>
<%= fmt_node(queue.online[i]) %>
<br/>
<% } %>
</td>
</tr>
<th>Members</th>
<td>
<% for (var i in queue.members) { %>
<%= fmt_node(queue.members[i]) %>
<br/>
<% } %>
</td>
</tr>

View File

@ -0,0 +1,6 @@
<tr>
<td>Queues [Streams]</td>
<td>
<span class="argument-link" field="definitionop" key="max-length-bytes" type="number">Max length bytes</span>
</td>
</tr>

View File

@ -0,0 +1,56 @@
<table class="facts facts-l">
<tr>
<th>State</th>
<td><%= fmt_object_state(queue) %></td>
</tr>
<% if(queue.consumers) { %>
<tr>
<th>Consumers</th>
<td><%= fmt_string(queue.consumers) %></td>
</tr>
<% } else if(queue.hasOwnProperty('consumer_details')) { %>
<tr>
<th>Consumers</th>
<td><%= fmt_string(queue.consumer_details.length) %></td>
</tr>
<% } %>
<% if(queue.hasOwnProperty('publishers')) { %>
<tr>
<th>Publishers</th>
<td><%= fmt_string(queue.publishers) %></td>
</tr>
<% } %>
<tr>
<th>Readers</th>
<td><%= fmt_table_short(queue.readers) %></td>
</tr>
<tr>
<th>Segments</th>
<td><%= fmt_string(queue.segments) %></td>
</tr>
</table>
<table class="facts">
<tr>
<td></td>
<th class="horizontal">Total</th>
</tr>
<tr>
<th>
Messages
<span class="help" id="queue-messages-stream"></span>
</th>
<td class="r">
<%= fmt_num_thousands(queue.messages) %>
</td>
</tr>
<tr>
</tr>
<tr>
<th>
Process memory
<span class="help" id="queue-process-memory"></span>
</th>
<td class="r"><%= fmt_bytes(queue.memory) %></td>
</tr>
</table>