Step 4A-6-C-R3.2.1 Executor Direct Transport Correction

#11
Files changed (1) hide show
  1. task_executor.py +43 -7
task_executor.py CHANGED
@@ -1,5 +1,5 @@
1
  # -*- coding: utf-8 -*-
2
- """SmartPaper R3.1 independent task executor.
3
 
4
  Bootstrap is intentionally lightweight: the child process validates the local
5
  request, claims the D1 task, writes a local claim handshake, and only then
@@ -147,16 +147,52 @@ class ExecutorApi:
147
  "Authorization": f"Bearer {_service_key()}",
148
  "Accept": "application/json",
149
  "Content-Type": "application/json",
150
- "User-Agent": "SmartPaper-R3.1-Executor/1.0",
151
  }
 
 
 
 
 
 
 
152
 
153
  def post(self, path: str, payload: dict, *, timeout=20) -> dict:
154
- response = requests.post(
155
- self.origin + path,
156
- headers=self.headers,
157
- json=payload,
158
- timeout=timeout,
 
159
  )
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
160
  try:
161
  data = response.json()
162
  except Exception as exc:
 
1
  # -*- coding: utf-8 -*-
2
+ """SmartPaper R3.2.1 independent task executor.
3
 
4
  Bootstrap is intentionally lightweight: the child process validates the local
5
  request, claims the D1 task, writes a local claim handshake, and only then
 
147
  "Authorization": f"Bearer {_service_key()}",
148
  "Accept": "application/json",
149
  "Content-Type": "application/json",
150
+ "User-Agent": "SmartPaper-R3.2.1-Executor/1.0",
151
  }
152
+ # HF Spaces can expose environment proxy settings that are less reliable
153
+ # for direct TLS handshakes to workers.dev. Reuse the proven SmartPaper
154
+ # transport policy: direct networking first, environment-aware networking
155
+ # only as a transport fallback. Business/HTTP errors never trigger fallback.
156
+ self._direct_session = requests.Session()
157
+ self._direct_session.trust_env = False
158
+ self._environment_session = requests.Session()
159
 
160
  def post(self, path: str, payload: dict, *, timeout=20) -> dict:
161
+ url = self.origin + path
162
+ response = None
163
+ last_transport_error = None
164
+ transports = (
165
+ ("direct", self._direct_session),
166
+ ("environment", self._environment_session),
167
  )
168
+ for index, (transport_name, session) in enumerate(transports):
169
+ try:
170
+ response = session.post(
171
+ url,
172
+ headers=self.headers,
173
+ json=payload,
174
+ timeout=timeout,
175
+ )
176
+ break
177
+ except (
178
+ requests.exceptions.SSLError,
179
+ requests.exceptions.Timeout,
180
+ requests.exceptions.ConnectionError,
181
+ ) as exc:
182
+ last_transport_error = exc
183
+ if index == 0:
184
+ logging.warning(
185
+ "[SP_EXECUTOR] transport_fallback path=%s from=direct to=environment error=%s",
186
+ path, type(exc).__name__,
187
+ )
188
+ continue
189
+ raise
190
+
191
+ if response is None:
192
+ if last_transport_error is not None:
193
+ raise last_transport_error
194
+ raise RuntimeError("executor_transport_unavailable")
195
+
196
  try:
197
  data = response.json()
198
  except Exception as exc: