Skip to content

Commit 995a4de

Browse files
committed
feat(node): default/internal timeout
1 parent 10bd97d commit 995a4de

File tree

6 files changed

+47
-5
lines changed

6 files changed

+47
-5
lines changed
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
"""node default timeout
2+
3+
Revision ID: a0a1125e46b1
4+
Revises: 99076844dee6
5+
Create Date: 2025-11-19 17:53:48.835236
6+
7+
"""
8+
from alembic import op
9+
import sqlalchemy as sa
10+
11+
12+
# revision identifiers, used by Alembic.
13+
revision = 'a0a1125e46b1'
14+
down_revision = '99076844dee6'
15+
branch_labels = None
16+
depends_on = None
17+
18+
19+
def upgrade() -> None:
20+
# ### commands auto generated by Alembic - please adjust! ###
21+
op.add_column('nodes', sa.Column('default_timeout', sa.Integer(), server_default=sa.text('(10)'), nullable=False))
22+
op.add_column('nodes', sa.Column('internal_timeout', sa.Integer(), server_default=sa.text('(15)'), nullable=False))
23+
# ### end Alembic commands ###
24+
25+
26+
def downgrade() -> None:
27+
# ### commands auto generated by Alembic - please adjust! ###
28+
op.drop_column('nodes', 'internal_timeout')
29+
op.drop_column('nodes', 'default_timeout')
30+
# ### end Alembic commands ###

app/db/models.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -522,6 +522,8 @@ class Node(Base):
522522
server_default=NodeConnectionType.grpc.name,
523523
)
524524
keep_alive: Mapped[int] = mapped_column(unique=False, default=0)
525+
default_timeout: Mapped[int] = mapped_column(default=10, server_default=text("10"))
526+
internal_timeout: Mapped[int] = mapped_column(default=15, server_default=text("15"))
525527

526528
@hybrid_property
527529
def reseted_uplink(self) -> int:

app/jobs/node_checker.py

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ async def verify_node_backend_health(node: PasarGuardNode, node_name: str) -> He
2424
Verify node health by checking backend stats.
2525
Returns updated health status.
2626
"""
27-
current_health = await node.get_health()
27+
current_health = await asyncio.wait_for(node.get_health(), timeout=10)
2828

2929
# Skip nodes that are not connected or invalid
3030
if current_health in (Health.NOT_CONNECTED, Health.INVALID):
@@ -55,8 +55,8 @@ async def update_node_connection_status(node_id: int, node: PasarGuardNode):
5555
Update node connection status by getting backend stats and version info.
5656
"""
5757
try:
58-
await asyncio.wait_for(node.get_backend_stats(), timeout=20)
59-
node_version, core_version = await asyncio.wait_for(node.get_versions(), timeout=20)
58+
await node.get_backend_stats()
59+
node_version, core_version = await asyncio.wait_for(node.get_versions(), timeout=10)
6060
async with GetDB() as db:
6161
await NodeOperation._update_single_node_status(
6262
db,
@@ -66,7 +66,7 @@ async def update_node_connection_status(node_id: int, node: PasarGuardNode):
6666
node_version=node_version,
6767
)
6868
except asyncio.TimeoutError:
69-
logger.warning(f"Node {node_id} connection status check timed out, will retry on next check")
69+
logger.warning(f"Node {node_id} get versions timed out, will retry on next check")
7070
return
7171
except NodeAPIError as e:
7272
if e.code > -3:
@@ -89,7 +89,7 @@ async def process_node_health_check(db_node: Node, node: PasarGuardNode):
8989
return
9090

9191
try:
92-
health = await asyncio.wait_for(verify_node_backend_health(node, db_node.name), timeout=20)
92+
health = await verify_node_backend_health(node, db_node.name)
9393
except asyncio.TimeoutError:
9494
if db_node.status == NodeStatus.connected:
9595
logger.warning(

app/models/node.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,8 @@ class Node(BaseModel):
4040
data_limit: int = Field(default=0)
4141
data_limit_reset_strategy: DataLimitResetStrategy = Field(default=DataLimitResetStrategy.no_reset)
4242
reset_time: int = Field(default=-1)
43+
default_timeout: int = Field(default=10)
44+
internal_timeout: int = Field(default=15)
4345

4446

4547
class NodeCreate(Node):
@@ -161,6 +163,8 @@ class NodeModify(NodeCreate):
161163
data_limit: int | None = None
162164
data_limit_reset_strategy: DataLimitResetStrategy | None = None
163165
reset_time: int | None = None
166+
default_timeout: int | None = None
167+
internal_timeout: int | None = None
164168

165169
model_config = ConfigDict(
166170
json_schema_extra={

app/node/__init__.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,8 @@ async def update_node(self, node: Node) -> PasarGuardNode:
4242
api_key=node.api_key,
4343
name=node.name,
4444
logger=self.logger,
45+
default_timeout=node.default_timeout,
46+
internal_timeout=node.internal_timeout,
4547
extra={"id": node.id, "usage_coefficient": node.usage_coefficient},
4648
)
4749

tests/api/test_node.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,8 @@ def sample_node_response(**overrides) -> NodeResponse:
6363
"data_limit": 0,
6464
"data_limit_reset_strategy": DataLimitResetStrategy.no_reset,
6565
"reset_time": -1,
66+
"default_timeout": 10,
67+
"internal_timeout": 15,
6668
"xray_version": "1.7.5",
6769
"node_version": "1.7.5",
6870
"status": NodeStatus.connected,
@@ -90,6 +92,8 @@ def node_create_payload(**overrides) -> dict:
9092
"data_limit": 0,
9193
"data_limit_reset_strategy": DataLimitResetStrategy.no_reset.value,
9294
"reset_time": -1,
95+
"default_timeout": 10,
96+
"internal_timeout": 15,
9397
}
9498
payload.update(overrides)
9599
return payload

0 commit comments

Comments
 (0)