diff --git a/.cursor/commands/create-improvement.md b/.cursor/commands/create-improvement.md index d89e327a..3411a64b 100644 --- a/.cursor/commands/create-improvement.md +++ b/.cursor/commands/create-improvement.md @@ -21,7 +21,7 @@ When the planned code changes are complete, the agent should take the following - Ensure changes are adequately tested 2. **Create Pull Request** - - Create a PR in draft mode + - Create a PR - Rename the PR with a title that follows the Conventional Commits 1.0.0 format - Update the PR description with: - A clear description of the problem and solution diff --git a/.env.example b/.env.example new file mode 100644 index 00000000..27c2330b --- /dev/null +++ b/.env.example @@ -0,0 +1,5 @@ +# Pinecone API Configuration +# Copy this file to .env and fill in your actual API key +# The .env file is gitignored and will not be committed + +PINECONE_API_KEY=your-api-key-here diff --git a/.github/workflows/cleanup-test-resources.yml b/.github/workflows/cleanup-test-resources.yml index 6d405cb5..09b940eb 100644 --- a/.github/workflows/cleanup-test-resources.yml +++ b/.github/workflows/cleanup-test-resources.yml @@ -14,7 +14,7 @@ on: age_threshold_days: description: 'Minimum age in days for resources to be deleted' required: false - default: '1' + default: 1 type: number dry_run: description: 'Preview deletions without executing (dry-run mode)' @@ -63,7 +63,9 @@ jobs: echo "Running cleanup with: $ARGS" # Run the cleanup utility - java -cp "build/libs/*:build/classes/java/main" \ + # Use only the shadow JAR (-all.jar) which contains all dependencies + # This avoids classpath conflicts from mixing regular JAR, shadow JAR, and other artifacts + java -cp build/libs/*-all.jar \ io.pinecone.helpers.IndexCleanupUtility $ARGS - name: Summary diff --git a/.github/workflows/pr.yml b/.github/workflows/pr.yml index 9acfb84c..6ef70a67 100644 --- a/.github/workflows/pr.yml +++ b/.github/workflows/pr.yml @@ -108,6 +108,6 @@ jobs: continue-on-error: true run: | echo "Running IndexCleanupUtility to clean up test indexes..." - java -cp "build/libs/*" io.pinecone.helpers.IndexCleanupUtility + java -cp build/libs/*-all.jar io.pinecone.helpers.IndexCleanupUtility env: PINECONE_API_KEY: ${{ secrets.PINECONE_API_KEY }} \ No newline at end of file diff --git a/.gitignore b/.gitignore index 018ae61d..70872e65 100644 --- a/.gitignore +++ b/.gitignore @@ -81,4 +81,10 @@ nb-configuration.xml ############################## .DS_Store +############################## +## Environment Variables +############################## +.env +.env.local + gen diff --git a/CHANGELOG.md b/CHANGELOG.md index 15580a5b..fa35cb45 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,8 @@ [comment]: <> (When bumping [pc:VERSION_LATEST_RELEASE] create a new entry below) ### Unreleased version +- Improve default HTTP timeout configuration: Set default timeouts to 30s connect, 120s read, and 30s write to accommodate long-running control plane operations like index creation/deletion. Users can still override with custom OkHttpClient if needed. + ### 6.1.0 - Add ResponseMetadataListener for dataplane operation observability diff --git a/README.md b/README.md index 4b07f152..bdf29a6e 100644 --- a/README.md +++ b/README.md @@ -63,9 +63,18 @@ public class InitializeClientExample { } ``` +#### Default HTTP Timeout Configuration + +The Pinecone client uses default HTTP timeouts that are suitable for most operations: +- **Connect timeout**: 30 seconds +- **Read timeout**: 120 seconds (accommodates long-running operations like index creation/deletion) +- **Write timeout**: 30 seconds + +These defaults are designed to handle operations that may take longer than typical HTTP requests, such as creating or deleting indexes which can take 30-120+ seconds. + #### Passing OkHttpClient for control plane operations -If you need to provide a custom `OkHttpClient`, you can do so by using the `withOkHttpClient()` method of the +If you need to provide a custom `OkHttpClient` with different timeout values or other custom configuration, you can do so by using the `withOkHttpClient()` method of the `Pinecone.Builder` class to pass in your `OkHttpClient` object. ```java @@ -74,10 +83,11 @@ import okhttp3.OkHttpClient; public class InitializeClientExample { public static void main(String[] args) { + // Example: Custom timeout configuration for specific use cases OkHttpClient.Builder builder = new OkHttpClient.Builder() - .connectTimeout(10, java.util.concurrent.TimeUnit.SECONDS) - .readTimeout(30, java.util.concurrent.TimeUnit.SECONDS) - .writeTimeout(30, java.util.concurrent.TimeUnit.SECONDS); + .connectTimeout(60, java.util.concurrent.TimeUnit.SECONDS) + .readTimeout(180, java.util.concurrent.TimeUnit.SECONDS) + .writeTimeout(60, java.util.concurrent.TimeUnit.SECONDS); OkHttpClient httpClient = builder.build(); diff --git a/src/integration/java/io/pinecone/integration/controlPlane/pod/ConfigureIndexTest.java b/src/integration/java/io/pinecone/integration/controlPlane/pod/ConfigureIndexTest.java index dac812f6..158de0d6 100644 --- a/src/integration/java/io/pinecone/integration/controlPlane/pod/ConfigureIndexTest.java +++ b/src/integration/java/io/pinecone/integration/controlPlane/pod/ConfigureIndexTest.java @@ -5,7 +5,6 @@ import io.pinecone.exceptions.PineconeForbiddenException; import io.pinecone.exceptions.PineconeNotFoundException; import io.pinecone.helpers.TestResourcesManager; -import okhttp3.OkHttpClient; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.Test; @@ -14,8 +13,6 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import java.util.concurrent.TimeUnit; - import static io.pinecone.helpers.AssertRetry.assertWithRetry; import static org.junit.jupiter.api.Assertions.*; @@ -25,11 +22,6 @@ public class ConfigureIndexTest { private static final Pinecone controlPlaneClient = new Pinecone .Builder(System.getenv("PINECONE_API_KEY")) .withSourceTag("pinecone_test") - .withOkHttpClient(new OkHttpClient.Builder() - .connectTimeout(10, TimeUnit.SECONDS) - .readTimeout(60, TimeUnit.SECONDS) - .writeTimeout(30, TimeUnit.SECONDS) - .build()) .build(); private static String indexName; diff --git a/src/integration/java/io/pinecone/integration/controlPlane/serverless/ReadCapacityAndSchemaTest.java b/src/integration/java/io/pinecone/integration/controlPlane/serverless/ReadCapacityAndSchemaTest.java index 24e8c19a..20fc1a72 100644 --- a/src/integration/java/io/pinecone/integration/controlPlane/serverless/ReadCapacityAndSchemaTest.java +++ b/src/integration/java/io/pinecone/integration/controlPlane/serverless/ReadCapacityAndSchemaTest.java @@ -2,14 +2,12 @@ import io.pinecone.clients.Pinecone; import io.pinecone.helpers.RandomStringBuilder; -import okhttp3.OkHttpClient; import org.junit.jupiter.api.*; import org.openapitools.db_control.client.ApiException; import org.openapitools.db_control.client.model.*; import java.util.HashMap; import java.util.Map; -import java.util.concurrent.TimeUnit; import static io.pinecone.helpers.TestUtilities.waitUntilIndexIsReady; import static io.pinecone.helpers.TestUtilities.waitUntilReadCapacityIsReady; @@ -20,11 +18,6 @@ public class ReadCapacityAndSchemaTest { private static final Pinecone controlPlaneClient = new Pinecone .Builder(System.getenv("PINECONE_API_KEY")) .withSourceTag("pinecone_test") - .withOkHttpClient(new OkHttpClient.Builder() - .connectTimeout(30, TimeUnit.SECONDS) - .readTimeout(120, TimeUnit.SECONDS) - .writeTimeout(30, TimeUnit.SECONDS) - .build()) .build(); @Test @@ -64,7 +57,7 @@ public void createServerlessIndexWithDedicatedReadCapacity() throws InterruptedE tags.put("read-capacity", "dedicated"); // Create index with Dedicated read capacity - ScalingConfigManual manual = new ScalingConfigManual().shards(2).replicas(2); + ScalingConfigManual manual = new ScalingConfigManual().shards(1).replicas(1); ReadCapacityDedicatedConfig dedicated = new ReadCapacityDedicatedConfig() .nodeType("t1") .scaling("Manual") diff --git a/src/main/java/io/pinecone/clients/Pinecone.java b/src/main/java/io/pinecone/clients/Pinecone.java index 9d7cc082..6147326f 100644 --- a/src/main/java/io/pinecone/clients/Pinecone.java +++ b/src/main/java/io/pinecone/clients/Pinecone.java @@ -17,6 +17,7 @@ import java.util.Arrays; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.TimeUnit; /** * The Pinecone class is the main entry point for interacting with Pinecone via the Java SDK. @@ -1798,8 +1799,29 @@ public Pinecone build() { } } + /** + * Builds an OkHttpClient with default timeout configuration suitable for Pinecone operations. + *

+ * Default timeout values: + *

+ *

+ * These defaults are designed to handle operations that may take longer than typical HTTP requests, + * such as creating or deleting indexes which can take 30-120+ seconds. For operations requiring + * different timeout values, users can provide a custom OkHttpClient via {@link Builder#withOkHttpClient(OkHttpClient)}. + * + * @param proxyConfig Optional proxy configuration. If provided, the client will route requests through the specified proxy. + * @return A configured OkHttpClient instance with default timeouts suitable for Pinecone operations. + */ static OkHttpClient buildOkHttpClient(ProxyConfig proxyConfig) { - OkHttpClient.Builder builder = new OkHttpClient.Builder(); + OkHttpClient.Builder builder = new OkHttpClient.Builder() + .connectTimeout(30, TimeUnit.SECONDS) + .readTimeout(120, TimeUnit.SECONDS) + .writeTimeout(30, TimeUnit.SECONDS); + if(proxyConfig != null) { Proxy proxy = new Proxy(Proxy.Type.HTTP, new InetSocketAddress(proxyConfig.getHost(), proxyConfig.getPort())); builder.proxy(proxy); diff --git a/src/main/java/io/pinecone/helpers/IndexCleanupUtility.java b/src/main/java/io/pinecone/helpers/IndexCleanupUtility.java index def32496..ca0a42e6 100644 --- a/src/main/java/io/pinecone/helpers/IndexCleanupUtility.java +++ b/src/main/java/io/pinecone/helpers/IndexCleanupUtility.java @@ -243,8 +243,9 @@ private boolean cleanupIndex(IndexModel index) throws Exception { pinecone.deleteIndex(indexName); logInfo("Successfully initiated deletion of index: %s", indexName); - // Add small delay to avoid rate limiting - Thread.sleep(1000); + // Add delay to avoid overwhelming the backend + logInfo("Waiting 30 seconds before next deletion..."); + Thread.sleep(30000); return true; } @@ -279,8 +280,9 @@ private boolean cleanupCollection(CollectionModel collection) throws Exception { pinecone.deleteCollection(collectionName); logInfo("Successfully initiated deletion of collection: %s", collectionName); - // Add small delay to avoid rate limiting - Thread.sleep(1000); + // Add delay to avoid overwhelming the backend + logInfo("Waiting 30 seconds before next deletion..."); + Thread.sleep(30000); return true; }