Skip to content

Replace ThreadPool with ThreadPoolExecutor for async_req#633

Open
yonatan-genai wants to merge 1 commit intopinecone-io:mainfrom
yonatan-genai:fix/replace-threadpool-with-executor
Open

Replace ThreadPool with ThreadPoolExecutor for async_req#633
yonatan-genai wants to merge 1 commit intopinecone-io:mainfrom
yonatan-genai:fix/replace-threadpool-with-executor

Conversation

@yonatan-genai
Copy link
Copy Markdown

@yonatan-genai yonatan-genai commented Apr 3, 2026

Summary

The async_req=True code path uses multiprocessing.pool.ThreadPool, which
depends on POSIX named semaphores (sem_open). This fails on platforms without
/dev/shm, notably AWS Lambda, Android, and Docker containers with restricted
shared memory.

ThreadPool is only used for thread-based parallelism here, not multiprocessing.
The ThreadPoolExecutor (from concurrent.futures) is already used internally
by the async_threadpool_executor path. This change reuses it for async_req
as well, eliminating the multiprocessing dependency entirely.

A .get() alias is added to the returned Future for backward compatibility
with existing code that calls .get(timeout) (the ApplyResult API) instead
of .result(timeout) (the Future API).

Changes

  • pinecone/openapi_support/api_client.py: Replace self.pool.apply_async()
    with self.threadpool_executor.submit(), remove ThreadPool property and
    multiprocessing imports
  • pinecone/adapters/response_adapters.py: Update UpsertResponseTransformer
    from ApplyResult to Future

Related


Note

Medium Risk
Touches the async request execution path and changes the concrete return type for async_req=True; subtle behavior differences between ApplyResult.get() and Future.result() (timeouts/cancellation/exceptions) could affect callers despite the .get compatibility alias.

Overview
Async OpenAPI requests (async_req=True) are migrated off multiprocessing.pool.ThreadPool to concurrent.futures.ThreadPoolExecutor, removing the multiprocessing/POSIX semaphore dependency and improving compatibility with restricted environments (e.g., Lambda containers).

ApiClient.call_api() now returns a Future (with a .get alias to .result for backward compatibility), and UpsertResponseTransformer is updated to wrap a Future instead of an ApplyResult while keeping the same .get()-based transformation behavior.

Written by Cursor Bugbot for commit 159cac6. This will update automatically on new commits. Configure here.

…sync_req

ThreadPool depends on POSIX named semaphores (sem_open), which fails on
platforms without /dev/shm such as AWS Lambda. The async_req code path
only needs thread-based parallelism, not multiprocessing.

This reuses the existing threadpool_executor property (already used by
the async_threadpool_executor path) for async_req as well. A .get()
alias is added to the returned Future for backward compatibility with
code that calls .get() instead of .result().

Removes the multiprocessing dependency from the client entirely.

<claude>
Copy link
Copy Markdown

@cursor cursor bot left a comment

Choose a reason for hiding this comment

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

Cursor Bugbot has reviewed your changes and found 1 potential issue.

Fix All in Cursor

Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

The SDK UpsertResponse dataclass.
"""
openapi_response = self._apply_result.get(timeout)
openapi_response = self._future.get(timeout)
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Future has no .get() method; use .result()

Medium Severity

UpsertResponseTransformer.get() calls self._future.get(timeout), but concurrent.futures.Future does not have a .get() method — its API is .result(timeout). This only works by accident because api_client.py monkey-patches future.get = future.result on the returned future. The internal UpsertResponseTransformer class should call self._future.result(timeout) directly instead of relying on the external monkey-patch, which is intended for backward compatibility of external callers.

Additional Locations (1)
Fix in Cursor Fix in Web

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