Skip to content

Commit cfa45a5

Browse files
authored
Add support for connection url for data plane operations only (#19)
* Add support for connection url * separate apiKey and connection url in connect() for better user experience * Handle removal of http:// or https:// in a robust manner * add validation before using configs
1 parent 4875867 commit cfa45a5

File tree

5 files changed

+94
-14
lines changed

5 files changed

+94
-14
lines changed

src/main/java/io/pinecone/PineconeClient.java

+5
Original file line numberDiff line numberDiff line change
@@ -36,4 +36,9 @@ public PineconeConnection connect(String indexName) {
3636
public PineconeConnection connect(PineconeConnectionConfig connectionConfig) {
3737
return new PineconeConnection(config, connectionConfig);
3838
}
39+
40+
public PineconeConnection connectWithUrl(String connectionUrl) {
41+
return connect(new PineconeConnectionConfig()
42+
.withConnectionUrl(connectionUrl));
43+
}
3944
}

src/main/java/io/pinecone/PineconeClientConfig.java

-4
Original file line numberDiff line numberDiff line change
@@ -100,10 +100,6 @@ public PineconeClientConfig withServerSideTimeoutSec(int serverSideTimeout) {
100100
void validate() {
101101
if (apiKey == null)
102102
throw new PineconeValidationException("Invalid Pinecone config: missing apiKey");
103-
if (environment == null)
104-
throw new PineconeValidationException("Invalid Pinecone config: missing environment");
105-
if (projectName == null)
106-
throw new PineconeValidationException("Invalid Pinecone config: missing projectName ");
107103
}
108104

109105
@Override

src/main/java/io/pinecone/PineconeConnection.java

+29-7
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@
22

33
import io.grpc.ManagedChannel;
44
import io.grpc.Metadata;
5-
import io.grpc.StatusRuntimeException;
65
import io.grpc.netty.GrpcSslContexts;
76
import io.grpc.netty.NegotiationType;
87
import io.grpc.netty.NettyChannelBuilder;
@@ -36,9 +35,10 @@ public class PineconeConnection implements AutoCloseable {
3635
private VectorServiceGrpc.VectorServiceStub asyncStub;
3736

3837
public PineconeConnection(PineconeClientConfig clientConfig, PineconeConnectionConfig connectionConfig) {
39-
connectionConfig.validate();
4038
this.connectionConfig = connectionConfig;
4139
this.clientConfig = clientConfig;
40+
validateConfigs();
41+
4242
channel = connectionConfig.getCustomChannelBuilder() != null
4343
? connectionConfig.getCustomChannelBuilder().apply(clientConfig, connectionConfig)
4444
: buildChannel(clientConfig, connectionConfig);
@@ -113,15 +113,37 @@ private VectorServiceGrpc.VectorServiceBlockingStub applyDefaultBlockingStubConf
113113
.withMaxOutboundMessageSize(DEFAULT_MAX_MESSAGE_SIZE);
114114
}
115115

116-
private static String getEndpoint(PineconeClientConfig clientConfig, PineconeConnectionConfig connectionConfig) {
117-
String endpoint = String.format("%s-%s.svc.%s.pinecone.io",
118-
connectionConfig.getIndexName(),
119-
clientConfig.getProjectName(),
120-
clientConfig.getEnvironment());
116+
static String getEndpoint(PineconeClientConfig clientConfig, PineconeConnectionConfig connectionConfig) {
117+
String endpoint = (connectionConfig.getConnectionUrl() != null) ?
118+
connectionConfig.getConnectionUrl().replaceFirst("https?://", "") :
119+
String.format("%s-%s.svc.%s.pinecone.io",
120+
connectionConfig.getIndexName(),
121+
clientConfig.getProjectName(),
122+
clientConfig.getEnvironment());
121123

122124
logger.debug("Pinecone endpoint is: " + endpoint);
123125

124126
return endpoint;
127+
}
128+
129+
void validateConfigs() throws PineconeValidationException {
130+
if (this.clientConfig == null) {
131+
throw new PineconeValidationException("PineconeClientConfiguration may not be null");
132+
}
125133

134+
if (this.connectionConfig == null) {
135+
throw new PineconeValidationException("PineconeConnectionConfig may not be null");
136+
}
137+
138+
this.clientConfig.validate();
139+
this.connectionConfig.validate();
140+
141+
if (this.connectionConfig.getIndexName() != null) {
142+
if (this.clientConfig.getEnvironment() == null || this.clientConfig.getProjectName() == null) {
143+
throw new PineconeValidationException("Cannot connect with indexName "
144+
+ this.connectionConfig.getIndexName()
145+
+ " unless PineconeClientConfig contains projectName and environment");
146+
}
147+
}
126148
}
127149
}

src/main/java/io/pinecone/PineconeConnectionConfig.java

+16-3
Original file line numberDiff line numberDiff line change
@@ -16,13 +16,16 @@ public class PineconeConnectionConfig {
1616
*/
1717
private String indexName;
1818

19+
private String connectionUrl;
20+
1921
/**
2022
* Creates a new default config.
2123
*/
2224
public PineconeConnectionConfig() {}
2325

2426
protected PineconeConnectionConfig(PineconeConnectionConfig other) {
2527
indexName = other.indexName;
28+
connectionUrl = other.connectionUrl;
2629
customChannelBuilder = other.customChannelBuilder;
2730
}
2831

@@ -42,6 +45,16 @@ public PineconeConnectionConfig withIndexName(String indexName) {
4245
return config;
4346
}
4447

48+
public String getConnectionUrl() {
49+
return connectionUrl;
50+
}
51+
52+
public PineconeConnectionConfig withConnectionUrl(String connectionUrl) {
53+
PineconeConnectionConfig config = new PineconeConnectionConfig(this);
54+
config.connectionUrl = connectionUrl;
55+
return config;
56+
}
57+
4558
public BiFunction<PineconeClientConfig, PineconeConnectionConfig, ManagedChannel> getCustomChannelBuilder() {
4659
return customChannelBuilder;
4760
}
@@ -53,16 +66,16 @@ public PineconeConnectionConfig withCustomChannelBuilder(BiFunction<PineconeClie
5366
}
5467

5568
void validate() {
56-
String messagePrefix = "Invalid Pinecone config: ";
57-
if (indexName == null)
58-
throw new PineconeValidationException(messagePrefix + "indexName must be specified");
69+
if (indexName == null && connectionUrl == null)
70+
throw new PineconeValidationException("Invalid PineconeConnectionConfig, indexName or connection url must be specified.");
5971
}
6072

6173
@Override
6274
public String toString() {
6375
return "PineconeConnectionConfig("
6476
+ "customChannelBuilder=" + getCustomChannelBuilder()
6577
+ ", indexName=" + getIndexName()
78+
+ ", connectionUrl=" + getConnectionUrl()
6679
+ ")";
6780
}
6881
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
package io.pinecone;
2+
3+
import org.junit.jupiter.api.Test;
4+
5+
import static org.junit.jupiter.api.Assertions.assertEquals;
6+
7+
public class PineconeConnectionTest {
8+
9+
@Test
10+
void testGetEndpointWithConnectionUrlWithHttps() {
11+
PineconeClientConfig clientConfig = new PineconeClientConfig().withApiKey("api-key");
12+
PineconeConnectionConfig connectionConfig = new PineconeConnectionConfig()
13+
.withConnectionUrl("https://steps-784-123-eqasas0aaaa1213aasasc-1223-f1eea9.svc.production.pinecone.io");
14+
15+
String endpoint = PineconeConnection.getEndpoint(clientConfig, connectionConfig);
16+
17+
assertEquals("steps-784-123-eqasas0aaaa1213aasasc-1223-f1eea9.svc.production.pinecone.io", endpoint);
18+
}
19+
20+
@Test
21+
void testGetEndpointWithConnectionUrlWithHttp() {
22+
PineconeClientConfig clientConfig = new PineconeClientConfig().withApiKey("api-key");
23+
PineconeConnectionConfig connectionConfig = new PineconeConnectionConfig()
24+
.withConnectionUrl("http://steps-784-123-eqasas0aaaa1213aasasc-1223-f1eea9.svc.production.pinecone.io");
25+
26+
String endpoint = PineconeConnection.getEndpoint(clientConfig, connectionConfig);
27+
28+
assertEquals("steps-784-123-eqasas0aaaa1213aasasc-1223-f1eea9.svc.production.pinecone.io", endpoint);
29+
}
30+
31+
@Test
32+
void testGetEndpointWithoutConnectionUrl() {
33+
PineconeClientConfig clientConfig = new PineconeClientConfig()
34+
.withApiKey("secret-api-key")
35+
.withEnvironment("aws-us-east4")
36+
.withProjectName("fee911a");
37+
PineconeConnectionConfig connectionConfig = new PineconeConnectionConfig()
38+
.withIndexName("step-2");
39+
40+
String endpoint = PineconeConnection.getEndpoint(clientConfig, connectionConfig);
41+
42+
assertEquals("step-2-fee911a.svc.aws-us-east4.pinecone.io", endpoint);
43+
}
44+
}

0 commit comments

Comments
 (0)