Skip to content

[MAIN-Feat] Automated proxy testing system with intelligent selection strategies#94

Merged
moda20 merged 8 commits into
masterfrom
Feature/updating-proxy-injection-and-handing
May 25, 2026
Merged

[MAIN-Feat] Automated proxy testing system with intelligent selection strategies#94
moda20 merged 8 commits into
masterfrom
Feature/updating-proxy-injection-and-handing

Conversation

@moda20
Copy link
Copy Markdown
Owner

@moda20 moda20 commented May 21, 2026

features:

  • Proxy validity recurrent check - New scheduled system job (ProxyTestingJob) that tests all configured proxies every 6 hours and exports comprehensive results with success/failure counts and duration metrics to output files
  • Individual proxy testing API - New POST /proxies/testProxy endpoint for manual on-demand testing of individual proxies with immediate status feedback
  • Intelligent proxy selection strategies - Multiple strategies per job (RANDOM, ROUND_ROBIN, LEAST_USED, SPECIFIC) with smart selection logic based on injection_count and use_count metrics. Strategies are saved in the jobParams object
  • Proxy usage analytics database - Added injection_count and use_count fields to proxy_job table schema for following proxy usage and injection

Notes

  • [impact] : You should provide a testing url via proxies.proxyTestingUrl environment variable so the tests function properly. This can also be configured in the config via the UI/ API
  • [impact] : System jobs auto-seeding on startup can be controlled via the jobs.seedSystemJobs configuration option
  • [impact] : SOCKS proxy is handled via an extra bun "polyfill" library as bun runtime doesn't handle socks proxies correctly yet.
  • [impact] : not setting a proxy strategy will choose the first linked proxy all the time. This will count as injection count and will count the usage time correctly.

Motivation and Context

Adding this feature has no goal to replace any more capable proxy setup, but to be able to give the local tasks more options natively as well as more information on error origins. This will help future debugging and monitoring

How Has This Been Tested?

  • Manual testing of individual proxy testing via POST /proxies/testProxy endpoint
  • Running and tweaking the system job

Screenshots (if applicable)

N/A - Backend feature changes

Types of changes

  • This change requires a documentation update

Related Issues

Additional Context

Summary by CodeRabbit

  • New Features

    • Added a proxy-testing API endpoint and a scheduled proxy-testing job that runs concurrent tests and exports results.
    • Configurable proxy selection strategies (Random, Round-Robin, Least-Used, Specific) and per-job proxy configuration.
    • Proxy injection now records injection/use counts and supports SOCKS with improved connection handling.
    • New config toggle to seed system jobs.
  • Chores

    • Added runtime libraries for HTTP error redaction and networking utilities; updated module resolution and HTTP service defaults.

Review Change Stack

moda20 added 5 commits May 20, 2026 22:55
strategy is saved in the job param

Updated the proxy schema to include proxy usage and injection numbers

using socks agent lib to handle axios socks proxy injection
…ectly yet

adding netBun fetch lib to handle socks proxies (this is temporary)

Adding a system proxy testing job

Adding system jobs database seeding feature, including the proxy testing job

Adding testProxy endpoint
Adding proxy strategy to jobConsumer
@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented May 21, 2026

Caution

Review failed

Pull request was closed or merged during review

📝 Walkthrough

Walkthrough

Adds proxy selection strategies, proxy injection/use counters and migration, SOCKS/non‑SOCKS Axios injection utilities, a concurrent ProxyTestJob and API, system-job seeding, config/types, and repository functions for testing and counting proxies.

Changes

Proxy Testing and Usage Tracking Infrastructure

Layer / File(s) Summary
Type definitions and contracts
src/types/proxies.ts
proxyPickingStrategy enum (RANDOM, ROUND_ROBIN, SPECIFIC, LEAST_USED) and jobProxyConfig interface for job-level proxy options.
Database schema and migration
prisma/migrations/..., prisma/schema.prisma
Adds proxy_job.injection_count and proxy_job.use_count (INTEGER NOT NULL DEFAULT 0); schema lines reformatted.
Configuration for seeding and testing
src/config/config.ts
Adds jobs.seedSystemJobs (bool, default true) and proxies.proxyTestingUrl (nullable string).
Initialization and system job seeding
src/initialization/dbSeed.ts, src/initialization/index.ts
Adds seedSystemJobs to insert ProxyTestingJob via createMany({skipDuplicates:true}) and runs it during initialization.
Job consumer proxy configuration
src/jobConsumer/jobConsumer.ts
injectProxies accepts optional proxyConfig; preRun forwards job.param?.proxyConfig for strategy/target selection.
Repository functions for proxy operations
src/repositories/proxies.ts
getAllProxies supports excludeDisabled; adds incrementProxyInjection, incrementProxyUsage, and testProxy(proxyId, axiosConfig?) (builds axios, injects proxy, performs GET, logs/redacts errors) and testProxyViaTheAPI.
Proxy injection and HTTP plumbing
src/utils/proxyUtils.ts, src/utils/httpRequestConfig.ts, src/utils/httpUtils/redactors.ts
Adds injectProxyIntoInstance (SOCKS via Bun fetch adapter or axios proxy defaults), getProxyConfigWithStrategy, refactors injectProxy to register interceptors and update counters, exports ProxyTestingHttpService and default error redactor.
Proxy testing job implementation
src/systemJobs/proxyTestingJob.ts
ProxyTestJob concurrently tests proxies with configurable concurrency and timeout via PromisePool, times results, logs successes/errors, exports results to a timestamped file, and completes with summary counts.
API endpoint, dependencies, and TS config
src/api/proxies/proxies.controller.ts, package.json, tsconfig.json
Adds POST /testProxy route (validates id via zod) that returns test status; adds axios-error-redact and netbun deps; sets compilerOptions.moduleResolution to bundler.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Possibly related PRs

Poem

🐰 I hop through proxies, one by one,
Counting hops and tests until it's done,
SOCKS or HTTP, I change my tune,
I log each victory beneath the moon,
Reports saved — carrot-sweet, I hum.

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately summarizes the main feature: an automated proxy testing system with intelligent selection strategies, which aligns with the core changes across the PR.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch Feature/updating-proxy-injection-and-handing

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 7

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/config/config.ts`:
- Around line 307-313: The config schema for proxies.proxyTestingUrl accepts any
string and should validate at load time; update the proxyTestingUrl entry in the
config schema (symbol: proxyTestingUrl) to validate URLs by changing its format
to a URL validator or a custom validation function that accepts null but throws
on malformed URL strings (e.g. use format: 'url' if your config library supports
it or provide a format: (val) => val === null || isValidUrl(val)). Keep default:
null and nullable: true so only non-null values are validated.

In `@src/repositories/proxies.ts`:
- Around line 239-246: testProxy can hang because the outbound call uses
axiosInstance.get(targetUrl) with no timeout; ensure the proxy test always uses
a finite timeout by setting a timeout value when creating the instance via
ProxyTestingHttpService.create (or by passing a timeout option to
axiosInstance.get), e.g., add a configurable numeric timeout (e.g., 5000 ms)
into the axiosConfig used by ProxyTestingHttpService.create or include { timeout
} in the get call, and preserve existing error handling in the .catch so timeout
errors are handled the same way; update places referencing
ProxyTestingHttpService.create and injectProxyIntoInstance to use the
timeout-aware axios instance.

In `@src/systemJobs/proxyTestingJob.ts`:
- Around line 54-63: In the catch blocks inside the proxy testing routine (the
catch that logs "Error encountered when testing the proxy" and the similar one
at lines 85-88), stop throwing raw runtime errors and instead await the
emitError call and throw a normalized, serializable object: await
this.emitError(...) before throwing, and throw an object containing serializable
fields such as { message: String(err), name: err?.name, stack: err?.stack,
proxyName } (omit non-serializable properties); update both the catch after the
proxy test and the later catch (the one emitting `proxy test failed`) to follow
this pattern so exported results remain JSON-serializable.
- Around line 19-24: Validate and sanitize the job params before constructing
the config: ensure concurrentTestRequests and requestTimeout (from
job.param?.config and in proxyTestingJobParams) are numeric and greater than
zero (or clamp to safe defaults like 1 for concurrentTestRequests and 1000/60000
for requestTimeout) to prevent zero, negative or non-numeric values breaking
PromisePool/test logic; perform these checks where config is built (the const
config assignment) and replace invalid values with defaults or throw a clear
error so downstream functions consuming config (concurrentTestRequests,
requestTimeout) always receive valid positive numbers.
- Around line 18-26: The run method declares an unused parameter options which
triggers the linter; either consume that parameter or remove it. Fix by using
the passed-in options object where appropriate (replace references to
this.options?.config?.proxies?.proxyTestingUrl with
options?.config?.proxies?.proxyTestingUrl and any other places referring to
this.options inside async run) or, if the instance field is intended, remove the
options parameter from the run signature and update callers accordingly; key
symbols to check are the run method signature, the options parameter, and the
this.options?.config?.proxies?.proxyTestingUrl reference.

In `@src/utils/proxyUtils.ts`:
- Around line 68-70: When handling proxyPickingStrategy.SPECIFIC in the switch
for selecting a proxy, don't return undefined on a missing target; instead
detect if proxies.find((p) => p.proxy_id === targetId) returns falsy and throw a
descriptive error (e.g., include targetId and available proxy IDs) so the caller
fails fast and surfaces a clear configuration/runtime error; update the SPECIFIC
case in the proxy selection logic to perform this check and throw rather than
falling through to the default path.
- Around line 62-67: The code currently sorts descending and returns the
most-used proxy for both proxyPickingStrategy.ROUND_ROBIN and
proxyPickingStrategy.LEAST_USED; change the sort to ascending so the least-used
proxy is selected (e.g., use a.injection_count > b.injection_count ? 1 : -1 for
ROUND_ROBIN and a.use_count > b.use_count ? 1 : -1 for LEAST_USED), and avoid
mutating the original array by sorting a copy (e.g., [...proxies].sort(...))[0];
update references to proxyPickingStrategy, ROUND_ROBIN, LEAST_USED,
injection_count, and use_count accordingly.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: 69828ed3-82d5-4ff8-8090-f21dca9b3502

📥 Commits

Reviewing files that changed from the base of the PR and between bbb964a and 3e82909.

⛔ Files ignored due to path filters (8)
  • bun.lock is excluded by !**/*.lock
  • src/generated/prisma/edge.js is excluded by !**/generated/**
  • src/generated/prisma/index-browser.js is excluded by !**/generated/**
  • src/generated/prisma/index.d.ts is excluded by !**/generated/**
  • src/generated/prisma/index.js is excluded by !**/generated/**
  • src/generated/prisma/package.json is excluded by !**/generated/**
  • src/generated/prisma/schema.prisma is excluded by !**/generated/**
  • src/generated/prisma/wasm.js is excluded by !**/generated/**
📒 Files selected for processing (14)
  • package.json
  • prisma/migrations/20260519183852_add_proxy_injection_and_use_count/migration.sql
  • prisma/schema.prisma
  • src/api/proxies/proxies.controller.ts
  • src/config/config.ts
  • src/initialization/dbSeed.ts
  • src/initialization/index.ts
  • src/jobConsumer/jobConsumer.ts
  • src/repositories/proxies.ts
  • src/systemJobs/proxyTestingJob.ts
  • src/types/proxies.ts
  • src/utils/httpRequestConfig.ts
  • src/utils/proxyUtils.ts
  • tsconfig.json

Comment thread src/config/config.ts
Comment thread src/repositories/proxies.ts
Comment thread src/systemJobs/proxyTestingJob.ts Outdated
Comment thread src/systemJobs/proxyTestingJob.ts
Comment thread src/systemJobs/proxyTestingJob.ts
Comment thread src/utils/proxyUtils.ts Outdated
Comment thread src/utils/proxyUtils.ts
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (2)
src/systemJobs/proxyTestingJob.ts (1)

60-63: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Don’t persist full probe responses in the scheduled job output.

testResponse.data is arbitrary remote content. Writing it for every proxy run can bloat output files and leak whatever the probe endpoint returns, while the PR objective only calls for status/counts and duration-style metrics.

Suggested fix
           return {
-            data: testResponse.data,
+            status: testResponse.status,
             duration,
             proxyName,
           };
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/systemJobs/proxyTestingJob.ts` around lines 60 - 63, The returned probe
result currently includes testResponse.data which may contain arbitrary remote
content; remove testResponse.data from the returned object in proxyTestingJob
(the block that returns { data: testResponse.data, duration, proxyName, ... })
and instead return only safe metrics such as duration, proxyName, status (e.g.,
testResponse.status or success boolean), and any counts you need (responseSize
as a number if you must but not raw body). Update any callers that expect data
to use the new status/metrics fields.
src/utils/proxyUtils.ts (1)

91-118: ⚠️ Potential issue | 🟠 Major | 🏗️ Heavy lift

Make selection and counter updates atomic for strategy-based picking.

injectProxy reads the current counts, picks a proxy from that snapshot, and only increments injection_count afterward. Under concurrent workers, ROUND_ROBIN and LEAST_USED can repeatedly choose the same proxy because they all race on the same stale counts. Move the selection plus increment into one database-side atomic step if these strategies need to stay fair under load.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/utils/proxyUtils.ts` around lines 91 - 118, The current flow calls
getJobProxies + getProxyConfigWithStrategy to pick a proxy and then calls
incrementProxyInjection afterwards, which allows races; instead implement a
single DB-side atomic operation that selects a proxy according to the given
strategy and increments its injection_count in the same transaction. Concretely:
add a new DB helper (e.g., pickAndIncrementProxy or selectAndIncrementProxy)
that takes jobId, proxyStrategy, optional targetProxyId and returns the chosen
proxy row with its id; replace the getJobProxies/getProxyConfigWithStrategy +
incrementProxyInjection sequence in this block with a single call to that new
helper and use its returned proxyJob for injectProxyIntoInstance and for wiring
the axios interceptor; leave incrementProxyUsage as an async per-request
increment inside the interceptor. Ensure injectProxyIntoInstance and the
interceptor reference the returned proxyJob.id.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/systemJobs/proxyTestingJob.ts`:
- Line 6: Remove the unused import defaultRedactor from the top of
src/systemJobs/proxyTestingJob.ts; locate the import statement "import
defaultRedactor from \"`@utils/httpUtils/redactors`\";" and delete it (or replace
with a used export if intended), then run the linter to ensure no other unused
imports remain.

---

Outside diff comments:
In `@src/systemJobs/proxyTestingJob.ts`:
- Around line 60-63: The returned probe result currently includes
testResponse.data which may contain arbitrary remote content; remove
testResponse.data from the returned object in proxyTestingJob (the block that
returns { data: testResponse.data, duration, proxyName, ... }) and instead
return only safe metrics such as duration, proxyName, status (e.g.,
testResponse.status or success boolean), and any counts you need (responseSize
as a number if you must but not raw body). Update any callers that expect data
to use the new status/metrics fields.

In `@src/utils/proxyUtils.ts`:
- Around line 91-118: The current flow calls getJobProxies +
getProxyConfigWithStrategy to pick a proxy and then calls
incrementProxyInjection afterwards, which allows races; instead implement a
single DB-side atomic operation that selects a proxy according to the given
strategy and increments its injection_count in the same transaction. Concretely:
add a new DB helper (e.g., pickAndIncrementProxy or selectAndIncrementProxy)
that takes jobId, proxyStrategy, optional targetProxyId and returns the chosen
proxy row with its id; replace the getJobProxies/getProxyConfigWithStrategy +
incrementProxyInjection sequence in this block with a single call to that new
helper and use its returned proxyJob for injectProxyIntoInstance and for wiring
the axios interceptor; leave incrementProxyUsage as an async per-request
increment inside the interceptor. Ensure injectProxyIntoInstance and the
interceptor reference the returned proxyJob.id.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: 4842de86-91ce-42a0-822c-d52d64bb65e1

📥 Commits

Reviewing files that changed from the base of the PR and between 3e82909 and 053be13.

⛔ Files ignored due to path filters (1)
  • bun.lock is excluded by !**/*.lock
📒 Files selected for processing (7)
  • package.json
  • src/api/proxies/proxies.controller.ts
  • src/repositories/proxies.ts
  • src/systemJobs/proxyTestingJob.ts
  • src/utils/httpRequestConfig.ts
  • src/utils/httpUtils/redactors.ts
  • src/utils/proxyUtils.ts

Comment thread src/systemJobs/proxyTestingJob.ts Outdated
@moda20 moda20 merged commit 4d3eb50 into master May 25, 2026
1 check passed
@moda20 moda20 deleted the Feature/updating-proxy-injection-and-handing branch May 25, 2026 14:45
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant