From 5805d4a6f09306d4e56fa7b7b8b85472a1dda236 Mon Sep 17 00:00:00 2001 From: Pankaj Soni Date: Mon, 13 Jan 2025 16:30:41 +0530 Subject: [PATCH] fix campaign clone --- cmd/admin.go | 1 + frontend/src/views/Campaigns.vue | 1 + frontend/yarn.lock | 125 ++++++++++++++++++------------- internal/manager/pipe.go | 88 +++++++++++++++++----- internal/manager/ratelimiter.go | 75 ------------------- 5 files changed, 144 insertions(+), 146 deletions(-) delete mode 100644 internal/manager/ratelimiter.go diff --git a/cmd/admin.go b/cmd/admin.go index 15c9c67b8..8dba04311 100644 --- a/cmd/admin.go +++ b/cmd/admin.go @@ -29,6 +29,7 @@ func handleGetServerConfig(c echo.Context) error { var ( app = c.Get("app").(*App) ) + out := serverConfig{ RootURL: app.constants.RootURL, FromEmail: app.constants.FromEmail, diff --git a/frontend/src/views/Campaigns.vue b/frontend/src/views/Campaigns.vue index f5242b21c..95be3b348 100644 --- a/frontend/src/views/Campaigns.vue +++ b/frontend/src/views/Campaigns.vue @@ -432,6 +432,7 @@ export default Vue.extend({ sliding_window: c.slidingWindow, sliding_window_rate: c.slidingWindowRate || 1, sliding_window_duration: c.slidingWindowDuration || '1h', + run_type: c.runType, }; if (c.archive) { diff --git a/frontend/yarn.lock b/frontend/yarn.lock index cb5a674a5..21e4d4d1b 100644 --- a/frontend/yarn.lock +++ b/frontend/yarn.lock @@ -69,16 +69,16 @@ resolved "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.21.5.tgz" integrity sha512-1SDgH6ZSPTlggy1yI6+Dbkiz8xzpHJEVAlF/AM1tHPLsf5STom9rwtjE4hKAF20FfXXNTFqEYXyJNWh1GiZedQ== -"@esbuild/android-arm64@0.21.5": - version "0.21.5" - resolved "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.21.5.tgz" - integrity sha512-c0uX9VAUBQ7dTDCjq+wdyGLowMdtR/GoC2U5IYk/7D1H1JYC0qseD7+11iMP2mRLN9RcCMRcjC4YMclCzGwS/A== - "@esbuild/android-arm@0.21.5": version "0.21.5" resolved "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.21.5.tgz" integrity sha512-vCPvzSjpPHEi1siZdlvAlsPxXl7WbOVUBBAowWug4rJHb68Ox8KualB+1ocNvT5fjv6wpkX6o/iEpbDrf68zcg== +"@esbuild/android-arm64@0.21.5": + version "0.21.5" + resolved "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.21.5.tgz" + integrity sha512-c0uX9VAUBQ7dTDCjq+wdyGLowMdtR/GoC2U5IYk/7D1H1JYC0qseD7+11iMP2mRLN9RcCMRcjC4YMclCzGwS/A== + "@esbuild/android-x64@0.21.5": version "0.21.5" resolved "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.21.5.tgz" @@ -104,16 +104,16 @@ resolved "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.21.5.tgz" integrity sha512-J95kNBj1zkbMXtHVH29bBriQygMXqoVQOQYA+ISs0/2l3T9/kj42ow2mpqerRBxDJnmkUDCaQT/dfNXWX/ZZCQ== -"@esbuild/linux-arm64@0.21.5": - version "0.21.5" - resolved "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.21.5.tgz" - integrity sha512-ibKvmyYzKsBeX8d8I7MH/TMfWDXBF3db4qM6sy+7re0YXya+K1cem3on9XgdT2EQGMu4hQyZhan7TeQ8XkGp4Q== - "@esbuild/linux-arm@0.21.5": version "0.21.5" resolved "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.21.5.tgz" integrity sha512-bPb5AHZtbeNGjCKVZ9UGqGwo8EUu4cLq68E95A53KlxAPRmUyYv2D6F0uUI65XisGOL1hBP5mTronbgo+0bFcA== +"@esbuild/linux-arm64@0.21.5": + version "0.21.5" + resolved "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.21.5.tgz" + integrity sha512-ibKvmyYzKsBeX8d8I7MH/TMfWDXBF3db4qM6sy+7re0YXya+K1cem3on9XgdT2EQGMu4hQyZhan7TeQ8XkGp4Q== + "@esbuild/linux-ia32@0.21.5": version "0.21.5" resolved "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.21.5.tgz" @@ -482,7 +482,7 @@ resolved "https://registry.npmjs.org/@types/json5/-/json5-0.0.29.tgz" integrity sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ== -"@types/node@*": +"@types/node@*", "@types/node@^18.0.0 || >=20.0.0": version "22.10.1" resolved "https://registry.npmjs.org/@types/node/-/node-22.10.1.tgz" integrity sha512-qKgsUwfHZV2WCWLAnVP1JqnpE6Im6h3Y0+fYgMTasNQ7V++CBX5OT1as0g0f+OyubbFqhf6XVNIsmN4IIhEgGQ== @@ -556,7 +556,7 @@ acorn-jsx@^5.3.2: resolved "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz" integrity sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ== -acorn@^8.9.0: +"acorn@^6.0.0 || ^7.0.0 || ^8.0.0", acorn@^8.9.0: version "8.14.0" resolved "https://registry.npmjs.org/acorn/-/acorn-8.14.0.tgz" integrity sha512-cl669nCJTZBsL97OF4kUQm5g5hC2uihk0NxY3WENAC0TYdILVkAyHymAntgxGkl7K+t0cXIrH5siy5S4XkFycA== @@ -724,7 +724,7 @@ asn1@~0.2.3: dependencies: safer-buffer "~2.1.0" -assert-plus@1.0.0, assert-plus@^1.0.0: +assert-plus@^1.0.0, assert-plus@1.0.0: version "1.0.0" resolved "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz" integrity sha512-NfJ4UzBCcQGLDlQq7nHxH+tv3kyZ0hHQqF5BO6J7tNJeP5do1llPr8dZ8zHonfhAu0PHAdMkSo+8o0wxg9lZWw== @@ -864,7 +864,7 @@ buffer@^5.7.1: base64-js "^1.3.1" ieee754 "^1.1.13" -bulma@0.9.4, bulma@^0.9.4: +bulma@^0.9.4, bulma@0.9.4: version "0.9.4" resolved "https://registry.npmjs.org/bulma/-/bulma-0.9.4.tgz" integrity sha512-86FlT5+1GrsgKbPLRRY7cGDg8fsJiP/jzTqXXVqiUZZ2aZT8uemEOHlU1CDU+TxklPEZ11HZNNWclRBBecP4CQ== @@ -903,7 +903,7 @@ chalk@^4.0.0, chalk@^4.1.0: ansi-styles "^4.1.0" supports-color "^7.1.0" -chart.js@^4.4.1: +chart.js@^4.1.1, chart.js@^4.4.1: version "4.4.7" resolved "https://registry.npmjs.org/chart.js/-/chart.js-4.4.7.tgz" integrity sha512-pwkcKfdzTMAU/+jNosKhNL2bHtJc/sSmYgVbuGTEDhzkrhmyihmP7vUc/5ZK9WopidMDHNe3Wm7jOd/WhuHWuw== @@ -1050,7 +1050,7 @@ cypress-file-upload@^5.0.2: resolved "https://registry.npmjs.org/cypress-file-upload/-/cypress-file-upload-5.0.8.tgz" integrity sha512-+8VzNabRk3zG6x8f8BWArF/xA/W0VK4IZNx3MV0jFWrJS/qKn8eHfa5nU73P9fOQAgwHFJx7zjg4lwOnljMO8g== -cypress@13.15.0: +cypress@>3.0.0, cypress@13.15.0: version "13.15.0" resolved "https://registry.npmjs.org/cypress/-/cypress-13.15.0.tgz" integrity sha512-53aO7PwOfi604qzOkCSzNlWquCynLlKE/rmmpSPcziRH6LNfaDUAklQT6WJIsD8ywxlIy+uVZsnTMCCQVd2kTw== @@ -1147,7 +1147,14 @@ de-indent@^1.0.2: resolved "https://registry.npmjs.org/de-indent/-/de-indent-1.0.2.tgz" integrity sha512-e/1zu3xH5MQryN2zdVaF0OrdNLUbvWxzMbi+iNA6Bky7l1RoP8a2fIbRocyHclXt/arDrrR6lL3TqFD9pMQTsg== -debug@^3.1.0, debug@^3.2.7: +debug@^3.1.0: + version "3.2.7" + resolved "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz" + integrity sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ== + dependencies: + ms "^2.1.1" + +debug@^3.2.7: version "3.2.7" resolved "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz" integrity sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ== @@ -1253,7 +1260,7 @@ end-of-stream@^1.1.0: dependencies: once "^1.4.0" -enquirer@^2.3.6: +enquirer@^2.3.6, "enquirer@>= 2.3.0 < 3": version "2.4.1" resolved "https://registry.npmjs.org/enquirer/-/enquirer-2.4.1.tgz" integrity sha512-rRqJg/6gd538VHvR3PSrdRBb/1Vy2YfzHqzvbhGIQpDRKIa4FgV/54b5Q1xYSxOOwKvjXweS26E0Q+nAMwp2pQ== @@ -1456,7 +1463,7 @@ eslint-module-utils@^2.12.0: dependencies: debug "^3.2.7" -eslint-plugin-import@^2.23.3, eslint-plugin-import@^2.26.0: +eslint-plugin-import@^2.23.3, eslint-plugin-import@^2.25.2, eslint-plugin-import@^2.26.0, eslint-plugin-import@>=2.2.0: version "2.31.0" resolved "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.31.0.tgz" integrity sha512-ixmkI62Rbc2/w8Vfxyh1jQRTdRTF52VxwRVHl/ykPAmqG+Nb7/kNn+byLP0LxPgI7zWA16Jt82SybJInmMia3A== @@ -1526,7 +1533,7 @@ eslint-plugin-react@^7.30.1: string.prototype.matchall "^4.0.11" string.prototype.repeat "^1.0.0" -eslint-plugin-vue@^9.19.2: +eslint-plugin-vue@^9.19.2, eslint-plugin-vue@^9.2.0: version "9.32.0" resolved "https://registry.npmjs.org/eslint-plugin-vue/-/eslint-plugin-vue-9.32.0.tgz" integrity sha512-b/Y05HYmnB/32wqVcjxjHZzNpwxj1onBOvqW89W+V+XNG1dRuaFbNd3vT9CLbr2LXjEoq+3vn8DanWf7XU22Ug== @@ -1562,7 +1569,7 @@ eslint-visitor-keys@^3.3.0, eslint-visitor-keys@^3.4.1, eslint-visitor-keys@^3.4 resolved "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz" integrity sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag== -eslint@^8.56.0: +"eslint@^2 || ^3 || ^4 || ^5 || ^6 || ^7.2.0 || ^8 || ^9", "eslint@^3 || ^4 || ^5 || ^6 || ^7 || ^8 || ^9", "eslint@^3 || ^4 || ^5 || ^6 || ^7 || ^8 || ^9.7", "eslint@^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0", "eslint@^6.0.0 || ^7.0.0 || >=8.0.0", "eslint@^6.2.0 || ^7.0.0 || ^8.0.0 || ^9.0.0", "eslint@^7.32.0 || ^8.2.0", eslint@^8.2.0, eslint@^8.56.0, eslint@>=6.0.0: version "8.57.1" resolved "https://registry.npmjs.org/eslint/-/eslint-8.57.1.tgz" integrity sha512-ypowyDxpVSYpkXr9WPv2PAZCtNip1Mv5KTW0SCurXv/9iOpcrH9PaqUElksqEB6pChqHGDRCFTyrZlGhnLNGiA== @@ -1682,7 +1689,7 @@ extract-zip@2.0.1: optionalDependencies: "@types/yauzl" "^2.9.1" -extsprintf@1.3.0, extsprintf@^1.2.0: +extsprintf@^1.2.0, extsprintf@1.3.0: version "1.3.0" resolved "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz" integrity sha512-11Ndz7Nv+mvAC1j0ktTa7fAb0vLyGGX+rMHNBYQviQDGU0Hw7lhctJANqbPhu9nV9/izT/IntTgZ7Im/9LJs9g== @@ -2052,16 +2059,16 @@ inherits@2: resolved "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz" integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ== -ini@2.0.0: - version "2.0.0" - resolved "https://registry.npmjs.org/ini/-/ini-2.0.0.tgz" - integrity sha512-7PnF4oN3CvZF23ADhA5wRaYEQpJ8qygSkbtTXWBeXWXmEVRXK+1ITciHWwHhsjv1TmW0MgacIv6hEi5pX5NQdA== - ini@^1.3.4: version "1.3.8" resolved "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz" integrity sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew== +ini@2.0.0: + version "2.0.0" + resolved "https://registry.npmjs.org/ini/-/ini-2.0.0.tgz" + integrity sha512-7PnF4oN3CvZF23ADhA5wRaYEQpJ8qygSkbtTXWBeXWXmEVRXK+1ITciHWwHhsjv1TmW0MgacIv6hEi5pX5NQdA== + internal-slot@^1.0.7: version "1.0.7" resolved "https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.7.tgz" @@ -2539,13 +2546,6 @@ mimic-fn@^2.1.0: resolved "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz" integrity sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg== -minimatch@9.0.1: - version "9.0.1" - resolved "https://registry.npmjs.org/minimatch/-/minimatch-9.0.1.tgz" - integrity sha512-0jWhJpD/MdhPXwPuiRkCbfYfSKp2qnn2eOc279qI7f+osl/l+prKSrvhg157zSYvx/1nmgn2NqdT6k2Z7zSH9w== - dependencies: - brace-expansion "^2.0.1" - minimatch@^3.0.5, minimatch@^3.1.1, minimatch@^3.1.2: version "3.1.2" resolved "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz" @@ -2560,6 +2560,13 @@ minimatch@^9.0.4: dependencies: brace-expansion "^2.0.1" +minimatch@9.0.1: + version "9.0.1" + resolved "https://registry.npmjs.org/minimatch/-/minimatch-9.0.1.tgz" + integrity sha512-0jWhJpD/MdhPXwPuiRkCbfYfSKp2qnn2eOc279qI7f+osl/l+prKSrvhg157zSYvx/1nmgn2NqdT6k2Z7zSH9w== + dependencies: + brace-expansion "^2.0.1" + minimist@^1.2.0, minimist@^1.2.6, minimist@^1.2.8: version "1.2.8" resolved "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz" @@ -2851,16 +2858,16 @@ proto-list@~1.2.1: resolved "https://registry.npmjs.org/proto-list/-/proto-list-1.2.4.tgz" integrity sha512-vtK/94akxsTMhe0/cbfpR+syPuszcuwhqVjJq26CuNDgFGj682oRBXOP5MJpv2r7JtE8MsiepGIqvvOTBwn2vA== -proxy-from-env@1.0.0: - version "1.0.0" - resolved "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.0.0.tgz" - integrity sha512-F2JHgJQ1iqwnHDcQjVBsq3n/uoaFL+iPW/eAeL7kVxy/2RrWaN4WroKjjvbsoRtv0ftelNyC01bjRhn/bhcf4A== - proxy-from-env@^1.1.0: version "1.1.0" resolved "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz" integrity sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg== +proxy-from-env@1.0.0: + version "1.0.0" + resolved "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.0.0.tgz" + integrity sha512-F2JHgJQ1iqwnHDcQjVBsq3n/uoaFL+iPW/eAeL7kVxy/2RrWaN4WroKjjvbsoRtv0ftelNyC01bjRhn/bhcf4A== + pump@^3.0.0: version "3.0.2" resolved "https://registry.npmjs.org/pump/-/pump-3.0.2.tgz" @@ -2874,13 +2881,6 @@ punycode@^2.1.0: resolved "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz" integrity sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg== -qs@6.13.0: - version "6.13.0" - resolved "https://registry.npmjs.org/qs/-/qs-6.13.0.tgz" - integrity sha512-+38qI9SOr8tfZ4QmJNplMUxqjbe7LKvvZgWdExBOmd+egZTtjLB67Gu0HRX3u/XOq7UU2Nx6nsjvS16Z9uwfpg== - dependencies: - side-channel "^1.0.6" - qs@^6.10.1: version "6.13.1" resolved "https://registry.npmjs.org/qs/-/qs-6.13.1.tgz" @@ -2888,6 +2888,13 @@ qs@^6.10.1: dependencies: side-channel "^1.0.6" +qs@6.13.0: + version "6.13.0" + resolved "https://registry.npmjs.org/qs/-/qs-6.13.0.tgz" + integrity sha512-+38qI9SOr8tfZ4QmJNplMUxqjbe7LKvvZgWdExBOmd+egZTtjLB67Gu0HRX3u/XOq7UU2Nx6nsjvS16Z9uwfpg== + dependencies: + side-channel "^1.0.6" + queue-microtask@^1.2.2: version "1.2.3" resolved "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz" @@ -3051,7 +3058,7 @@ safer-buffer@^2.0.2, safer-buffer@^2.1.0, safer-buffer@~2.1.0: resolved "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz" integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg== -sass@^1.34.0: +sass@*, sass@^1.34.0: version "1.82.0" resolved "https://registry.npmjs.org/sass/-/sass-1.82.0.tgz" integrity sha512-j4GMCTa8elGyN9A7x7bEglx0VgSpNUG4W4wNedQ33wSMdnkqQCT8HTwOaVSV4e6yQovcu/3Oc4coJP/l0xhL2Q== @@ -3062,7 +3069,12 @@ sass@^1.34.0: optionalDependencies: "@parcel/watcher" "^2.4.1" -semver@^6.3.0, semver@^6.3.1: +semver@^6.3.0: + version "6.3.1" + resolved "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz" + integrity sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA== + +semver@^6.3.1: version "6.3.1" resolved "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz" integrity sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA== @@ -3144,7 +3156,7 @@ slice-ansi@^4.0.0: astral-regex "^2.0.0" is-fullwidth-code-point "^3.0.0" -"source-map-js@>=0.6.2 <2.0.0", source-map-js@^1.2.1: +source-map-js@^1.2.1, "source-map-js@>=0.6.2 <2.0.0": version "1.2.1" resolved "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz" integrity sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA== @@ -3187,7 +3199,16 @@ string-width@^4.1.0, string-width@^4.2.0: is-fullwidth-code-point "^3.0.0" strip-ansi "^6.0.1" -string-width@^5.0.1, string-width@^5.1.2: +string-width@^5.0.1: + version "5.1.2" + resolved "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz" + integrity sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA== + dependencies: + eastasianwidth "^0.2.0" + emoji-regex "^9.2.2" + strip-ansi "^7.0.1" + +string-width@^5.1.2: version "5.1.2" resolved "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz" integrity sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA== @@ -3517,7 +3538,7 @@ verror@1.10.0: core-util-is "1.0.2" extsprintf "^1.2.0" -vite@^5.1.8: +"vite@^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0", vite@^5.1.8: version "5.4.11" resolved "https://registry.npmjs.org/vite/-/vite-5.4.11.tgz" integrity sha512-c7jFQRklXua0mTzneGW9QVyxFjUgwcihC4bXEtujIo2ouWCe1Ajt/amn2PCxYnhYfd5k09JX3SB7OYWFKYqj8Q== @@ -3564,7 +3585,7 @@ vue-template-compiler@^2.6.12: de-indent "^1.0.2" he "^1.2.0" -vue@^2.7.14: +vue@^2.0.0, vue@^2.4.3, vue@^2.6.11, vue@^2.7.0-0, vue@^2.7.14, "vue@^3.0.0-0 || ^2.7.0": version "2.7.16" resolved "https://registry.npmjs.org/vue/-/vue-2.7.16.tgz" integrity sha512-4gCtFXaAA3zYZdTp5s4Hl2sozuySsgz4jy1EnpBHNfpMa9dK1ZCG7viqBPCwXtmgc8nHqUsAu3G4gtmXkkY3Sw== diff --git a/internal/manager/pipe.go b/internal/manager/pipe.go index 12ec43797..c36649c5d 100644 --- a/internal/manager/pipe.go +++ b/internal/manager/pipe.go @@ -8,21 +8,22 @@ import ( "github.com/knadh/listmonk/models" "github.com/paulbellamy/ratecounter" - "go.uber.org/ratelimit" ) type pipe struct { - camp *models.Campaign - rate *ratecounter.RateCounter - ratelimiter ratelimit.Limiter - wg *sync.WaitGroup - sent atomic.Int64 - lastID atomic.Uint64 - errors atomic.Uint64 - stopped atomic.Bool - flagSubQueued atomic.Bool - withErrors atomic.Bool - m *Manager + camp *models.Campaign + rate *ratecounter.RateCounter + wg *sync.WaitGroup + sent atomic.Int64 + lastID atomic.Uint64 + errors atomic.Uint64 + stopped atomic.Bool + flagSubQueued atomic.Bool + withErrors atomic.Bool + m *Manager + slidingStart time.Time + SlidingWindowDuration time.Duration + slidingCount int } // newPipe adds a campaign to the process queue. @@ -43,16 +44,19 @@ func (m *Manager) newPipe(c *models.Campaign) (*pipe, error) { return nil, err } + dur, _ := time.ParseDuration(c.SlidingWindowDuration) + // Add the campaign to the active map. p := &pipe{ - camp: c, - rate: ratecounter.NewRateCounter(time.Minute), - wg: &sync.WaitGroup{}, - m: m, + camp: c, + rate: ratecounter.NewRateCounter(time.Minute), + wg: &sync.WaitGroup{}, + m: m, + slidingStart: time.Now(), + SlidingWindowDuration: dur, + slidingCount: 0, } - p.attachRateLimiter() - // Increment the waitgroup so that Wait() blocks immediately. This is necessary // as a campaign pipe is created first and subscribers/messages under it are // fetched asynchronolusly later. The messages each add to the wg and that @@ -121,7 +125,29 @@ func (p *pipe) NextSubscribers(result chan *NextSubResult) { // Check if the sliding window is active. if hasSliding { - p.ratelimiter.Take() + diff := time.Now().Sub(p.slidingStart) + + // Window has expired. Reset the clock. + if diff >= p.SlidingWindowDuration { + p.slidingStart = time.Now() + p.slidingCount = 0 + continue + } + + // Have the messages exceeded the limit? + p.slidingCount++ + if p.slidingCount >= p.camp.SlidingWindowRate { + wait := p.SlidingWindowDuration - diff + + p.m.log.Printf("messages exceeded (%d) for the window (%v since %s). Sleeping for %s.", + p.slidingCount, + p.SlidingWindowDuration, + p.slidingStart.Format(time.RFC822Z), + wait.Round(time.Second)*1) + + p.slidingCount = 0 + time.Sleep(wait) + } } } @@ -171,6 +197,30 @@ func (p *pipe) newMessage(s models.Subscriber) (CampaignMessage, error) { return msg, nil } +// long running campaign, wait for event +func (p *pipe) waitForEvent() bool { + ticker := time.NewTicker(1 * time.Minute) + defer ticker.Stop() + + p.m.log.Printf("campaign: %s, will wait for events, at 1 min interval", p.camp.Name) + + for { + select { + case <-ticker.C: + p.m.log.Printf("campaign %s, stopped: %t, has: %t", p.camp.Name, p.stopped.Load(), p.flagSubQueued.Load()) + if p.stopped.Load() { + return false + } + + if p.flagSubQueued.Load() { + p.flagSubQueued.Store(false) + p.m.log.Printf("campaign: %s, got event", p.camp.Name) + return true + } + } + } +} + func (p *pipe) cleanup() { defer func() { p.m.pipesMut.Lock() diff --git a/internal/manager/ratelimiter.go b/internal/manager/ratelimiter.go deleted file mode 100644 index 581de71cf..000000000 --- a/internal/manager/ratelimiter.go +++ /dev/null @@ -1,75 +0,0 @@ -package manager - -import ( - "time" - - "go.uber.org/ratelimit" -) - -type customClock struct { - p *pipe -} - -func (p *pipe) attachRateLimiter() { - if !p.camp.SlidingWindow { - return - } - - dur, _ := time.ParseDuration(p.camp.SlidingWindowDuration) - clock := &customClock{ - p: p, - } - - p.ratelimiter = ratelimit.New(p.camp.SlidingWindowRate, - ratelimit.WithSlack(0), - ratelimit.Per(dur), - ratelimit.WithClock(clock), - ) -} - -func (c *customClock) Now() time.Time { return time.Now() } - -// pause strict on hitting rate limit -func (c *customClock) Sleep(wait time.Duration) { - startTime := time.Now() - ticker := time.NewTicker(1 * time.Second) - defer ticker.Stop() - - for { - select { - case <-ticker.C: - - if c.p.stopped.Load() { - return - } - - if time.Since(startTime) > wait { - return - } - } - } -} - -// long running campaign, wait for event -func (p *pipe) waitForEvent() bool { - ticker := time.NewTicker(1 * time.Minute) - defer ticker.Stop() - - p.m.log.Printf("campaign: %s, will wait for events, at 1 min interval", p.camp.Name) - - for { - select { - case <-ticker.C: - p.m.log.Printf("campaign %s, stopped: %t, has: %t", p.camp.Name, p.stopped.Load(), p.flagSubQueued.Load()) - if p.stopped.Load() { - return false - } - - if p.flagSubQueued.Load() { - p.flagSubQueued.Store(false) - p.m.log.Printf("campaign: %s, got event", p.camp.Name) - return true - } - } - } -}