feat(mikrotik): implement batch removal of address lists with fallback to individual deletes for improved efficiency and error handling
Publish Fast Tabler Docker image / build-and-push-fast (push) Successful in 1m52s
Publish Fast Tabler Docker image / build-and-push-fast (push) Successful in 1m52s
This commit is contained in:
@@ -1475,6 +1475,58 @@ async function getAddressLists(req, res) {
|
||||
}
|
||||
|
||||
const ADDRESS_LIST_PATH = 'ip/firewall/address-list';
|
||||
const ADDRESS_LIST_REMOVE_CHUNK_SIZE = 100;
|
||||
|
||||
function chunkArray(items, size) {
|
||||
if (!Array.isArray(items) || items.length === 0) return [];
|
||||
const chunkSize = Math.max(1, Number(size) || 1);
|
||||
const chunks = [];
|
||||
for (let i = 0; i < items.length; i += chunkSize) {
|
||||
chunks.push(items.slice(i, i + chunkSize));
|
||||
}
|
||||
return chunks;
|
||||
}
|
||||
|
||||
/**
|
||||
* Удаление address-list по .id:
|
||||
* 1) пытаемся батчем через POST .../remove { numbers: "*1,*2" }
|
||||
* 2) при ошибке откатываемся к поштучному DELETE, чтобы не ломать совместимость.
|
||||
*/
|
||||
async function removeAddressListIds(client, ids) {
|
||||
const normalizedIds = [...new Set(
|
||||
(Array.isArray(ids) ? ids : [])
|
||||
.map((id) => String(id || '').trim())
|
||||
.filter(Boolean)
|
||||
)];
|
||||
if (normalizedIds.length === 0) return 0;
|
||||
|
||||
let removed = 0;
|
||||
const chunks = chunkArray(normalizedIds, ADDRESS_LIST_REMOVE_CHUNK_SIZE);
|
||||
|
||||
for (const chunk of chunks) {
|
||||
try {
|
||||
await client.command(`${ADDRESS_LIST_PATH}/remove`, { numbers: chunk.join(',') });
|
||||
removed += chunk.length;
|
||||
continue;
|
||||
} catch (err) {
|
||||
console.warn(
|
||||
`[address-lists] batch remove fallback (${chunk.length} ids):`,
|
||||
err?.message || String(err)
|
||||
);
|
||||
}
|
||||
|
||||
for (const id of chunk) {
|
||||
try {
|
||||
await rosRemove(client, ADDRESS_LIST_PATH, id);
|
||||
removed++;
|
||||
} catch (err) {
|
||||
console.warn(`[address-lists] remove ${id}:`, err?.message);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return removed;
|
||||
}
|
||||
|
||||
/**
|
||||
* POST /api/mikrotik/address-lists/apply-summary
|
||||
@@ -1487,7 +1539,9 @@ async function applyAddressListSummary(req, res) {
|
||||
if (!serverId) {
|
||||
return sendError(res, 400, 'serverId is required', 'E_BAD_REQUEST');
|
||||
}
|
||||
const ids = Array.isArray(removeIds) ? removeIds.filter((id) => id != null && String(id).trim()) : [];
|
||||
const ids = Array.isArray(removeIds)
|
||||
? [...new Set(removeIds.map((id) => String(id || '').trim()).filter(Boolean))]
|
||||
: [];
|
||||
const entries = Array.isArray(addEntries)
|
||||
? addEntries.filter((e) => e && (e.address || e.list))
|
||||
: [];
|
||||
@@ -1507,15 +1561,7 @@ async function applyAddressListSummary(req, res) {
|
||||
let removed = 0;
|
||||
let added = 0;
|
||||
|
||||
for (const id of ids) {
|
||||
try {
|
||||
const pathId = String(id).trim();
|
||||
await rosRemove(client, ADDRESS_LIST_PATH, pathId);
|
||||
removed++;
|
||||
} catch (err) {
|
||||
console.warn(`[address-lists] remove ${id}:`, err?.message);
|
||||
}
|
||||
}
|
||||
removed = await removeAddressListIds(client, ids);
|
||||
|
||||
for (const entry of entries) {
|
||||
try {
|
||||
|
||||
Reference in New Issue
Block a user