Skip to content

Commit 84a12f2

Browse files
committed
update
1 parent fb520c0 commit 84a12f2

File tree

16 files changed

+1520
-121
lines changed

16 files changed

+1520
-121
lines changed

astra-db-java/src/main/java/com/datastax/astra/client/Collection.java

Lines changed: 87 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
import com.datastax.astra.client.exception.TooManyDocumentsToCountException;
2626
import com.datastax.astra.client.model.BulkWriteOptions;
2727
import com.datastax.astra.client.model.BulkWriteResult;
28+
import com.datastax.astra.client.model.CollectionIdTypes;
2829
import com.datastax.astra.client.model.CollectionInfo;
2930
import com.datastax.astra.client.model.CollectionOptions;
3031
import com.datastax.astra.client.model.Command;
@@ -44,21 +45,30 @@
4445
import com.datastax.astra.client.model.InsertManyOptions;
4546
import com.datastax.astra.client.model.InsertManyResult;
4647
import com.datastax.astra.client.model.InsertOneResult;
48+
import com.datastax.astra.client.model.ObjectId;
4749
import com.datastax.astra.client.model.Page;
4850
import com.datastax.astra.client.model.ReplaceOneOptions;
51+
import com.datastax.astra.client.model.UUIDv6;
52+
import com.datastax.astra.client.model.UUIDv7;
4953
import com.datastax.astra.client.model.Update;
5054
import com.datastax.astra.client.model.UpdateOneOptions;
5155
import com.datastax.astra.client.model.UpdateResult;
5256
import com.datastax.astra.internal.command.AbstractCommandRunner;
5357
import com.datastax.astra.internal.api.ApiResponse;
58+
import com.datastax.astra.internal.command.LoggingCommandObserver;
5459
import com.datastax.astra.internal.utils.Assert;
60+
import com.datastax.astra.internal.utils.CustomEJsonInstantDeserializer;
61+
import com.datastax.astra.internal.utils.CustomUuidv6Serializer;
5562
import com.datastax.astra.internal.utils.JsonUtils;
5663
import lombok.Getter;
5764
import lombok.extern.slf4j.Slf4j;
5865

66+
import java.time.Instant;
5967
import java.util.ArrayList;
6068
import java.util.List;
69+
import java.util.Map;
6170
import java.util.Optional;
71+
import java.util.UUID;
6272
import java.util.concurrent.Callable;
6373
import java.util.concurrent.CompletableFuture;
6474
import java.util.concurrent.ExecutorService;
@@ -125,6 +135,16 @@ public class Collection<T> extends AbstractCommandRunner {
125135
/** Api Endpoint for the Database, if using an astra environment it will contain the database id and the database region. */
126136
private final String apiEndpoint;
127137

138+
/**
139+
* Keep Collection options in -memory to avoid multiple calls to the API.
140+
*/
141+
private CollectionOptions options;
142+
143+
/**
144+
* Check if options has been fetched
145+
*/
146+
private boolean optionChecked = false;
147+
128148
/**
129149
* Constructs an instance of a collection within the specified database. This constructor
130150
* initializes the collection with a given name and associates it with a specific class type
@@ -257,10 +277,11 @@ public CollectionInfo getDefinition() {
257277
* such as vector and indexing options. Returns {@code null} if no options are set or applicable.
258278
*/
259279
public CollectionOptions getOptions() {
260-
return Optional
261-
.ofNullable(getDefinition()
262-
.getOptions())
263-
.orElse(new CollectionOptions());
280+
if (!optionChecked) {
281+
options = Optional.ofNullable(getDefinition().getOptions()).orElse(new CollectionOptions());
282+
optionChecked = true;
283+
}
284+
return options;
264285
}
265286

266287
/**
@@ -545,7 +566,51 @@ public final CompletableFuture<InsertOneResult> insertOneAsync(T document, Strin
545566
private InsertOneResult _insertOne(Document document) {
546567
Assert.notNull(document, "document");
547568
Command insertOne = Command.create("insertOne").withDocument(document);
548-
return new InsertOneResult(runCommand(insertOne).getStatusKeyAsList("insertedIds", Object.class).get(0));
569+
Object documentId = runCommand(insertOne)
570+
.getStatusKeyAsList("insertedIds", Object.class)
571+
.get(0);
572+
return new InsertOneResult(unmarshallDocumentId(documentId));
573+
}
574+
575+
/**
576+
* Unmarshall the document id.
577+
*
578+
* @param id
579+
* object id returned by the server
580+
* @return
581+
* unmarshalled id
582+
*/
583+
@SuppressWarnings("unchecked")
584+
protected Object unmarshallDocumentId(Object id) {
585+
if (id instanceof Map) {
586+
// only maps will required to be unmarshalled
587+
Map<String, Object> mapId = (Map<String, Object>) id;
588+
if (mapId.containsKey("$date")) {
589+
// eJson date
590+
return Instant.ofEpochMilli((Long) mapId.get("$date"));
591+
}
592+
if (mapId.containsKey("$uuid")) {
593+
// defaultId with UUID
594+
UUID uid = UUID.fromString((String) mapId.get("$uuid"));
595+
if (getOptions() != null && getOptions().getDefaultId() != null) {
596+
switch(getOptions().getDefaultId().get("type")) {
597+
case uuidv6:
598+
return new UUIDv6(uid);
599+
case uuidv7:
600+
return new UUIDv7(uid);
601+
default:
602+
return uid;
603+
}
604+
}
605+
throw new IllegalStateException("Returned is is a UUID, but no defaultId is set in the collection definition.");
606+
}
607+
if (mapId.containsKey("$objectId")) {
608+
// defaultId with ObjectId
609+
return new ObjectId((String) mapId.get("$objectId"));
610+
}
611+
throw new IllegalArgumentException("Cannot marshall id " + id);
612+
}
613+
return id;
549614
}
550615

551616
/**
@@ -786,7 +851,11 @@ private Callable<InsertManyResult> getInsertManyResultCallable(List<? extends T>
786851
Command insertMany = new Command("insertMany")
787852
.withDocuments(documents.subList(start, end))
788853
.withOptions(new Document().append("ordered", options.isOrdered()));
789-
return new InsertManyResult(runCommand(insertMany).getStatusKeyAsList("insertedIds", Object.class));
854+
return new InsertManyResult(runCommand(insertMany)
855+
.getStatusKeyAsList("insertedIds", Object.class)
856+
.stream()
857+
.map(this::unmarshallDocumentId)
858+
.collect(Collectors.toList()));
790859
};
791860
}
792861

@@ -1792,6 +1861,18 @@ public BulkWriteResult bulkWrite(List<Command> commands, BulkWriteOptions option
17921861

17931862
// --- Required for the Command Runner ---
17941863

1864+
/**
1865+
* Register the logging listener to the collection.
1866+
*
1867+
* @return
1868+
* self reference
1869+
*/
1870+
public Collection<T> enableLogging() {
1871+
registerListener("logger", new LoggingCommandObserver(Collection.class));
1872+
return this;
1873+
}
1874+
1875+
17951876
/** {@inheritDoc} */
17961877
@Override
17971878
protected String getApiEndpoint() {

astra-db-java/src/main/java/com/datastax/astra/client/Database.java

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@
3232
import com.datastax.astra.client.admin.DataAPIDatabaseAdmin;
3333
import com.datastax.astra.internal.api.AstraApiEndpoint;
3434
import com.datastax.astra.client.admin.AstraDBDatabaseAdmin;
35+
import com.datastax.astra.internal.command.LoggingCommandObserver;
3536
import com.datastax.astra.internal.utils.JsonUtils;
3637
import lombok.Getter;
3738
import lombok.NonNull;
@@ -377,6 +378,17 @@ public void dropCollection(String collectionName) {
377378

378379
// --- Required for the Command Runner ---
379380

381+
/**
382+
* Register the logging listener to the collection.
383+
*
384+
* @return
385+
* self reference
386+
*/
387+
public Database enableLogging() {
388+
registerListener("logger", new LoggingCommandObserver(Database.class));
389+
return this;
390+
}
391+
380392
/** {@inheritDoc} */
381393
@Override
382394
protected String getApiEndpoint() {

astra-db-java/src/main/java/com/datastax/astra/client/model/Document.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -236,6 +236,7 @@ public <T> T getId(@NonNull final Class<T> clazz) {
236236
return get(ID, clazz);
237237
}
238238

239+
239240
/**
240241
* Set value for the identifier.
241242
*

astra-db-java/src/main/java/com/datastax/astra/client/model/UUIDv6.java

Lines changed: 7 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,13 @@ public class UUIDv6 {
3434
*/
3535
private final UUID uuid;
3636

37+
/**
38+
* Default constructor.
39+
*/
40+
public UUIDv6() {
41+
this(Generators.timeBasedReorderedGenerator().generate());
42+
}
43+
3744
/**
3845
* Constructor.
3946
*
@@ -72,16 +79,4 @@ public static UUIDv6 fromString(String strUUID) {
7279
return new UUIDv6(UUID.fromString(strUUID));
7380
}
7481

75-
/**
76-
* Generate a new UUIDv6.
77-
*
78-
* @return
79-
* uuid v6.
80-
*/
81-
public static UUIDv6 generate() {
82-
return new UUIDv6(Generators.timeBasedReorderedGenerator().generate());
83-
}
84-
85-
86-
8782
}

astra-db-java/src/main/java/com/datastax/astra/client/model/UUIDv7.java

Lines changed: 7 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,13 @@ public class UUIDv7 {
3535
*/
3636
private final UUID uuid;
3737

38+
/**
39+
* Default constructor.
40+
*/
41+
public UUIDv7() {
42+
this(Generators.timeBasedEpochRandomGenerator(new SecureRandom()).generate());
43+
}
44+
3845
/**
3946
* Constructor.
4047
*
@@ -73,14 +80,4 @@ public static UUIDv7 fromString(String strUUID) {
7380
return new UUIDv7(UUID.fromString(strUUID));
7481
}
7582

76-
/**
77-
* Generate a new UUIDv6.
78-
*
79-
* @return
80-
* uuid v6.
81-
*/
82-
public static UUIDv7 generate() {
83-
return new UUIDv7(Generators.timeBasedEpochRandomGenerator(new SecureRandom()).generate());
84-
}
85-
8683
}

astra-db-java/src/main/java/com/datastax/astra/internal/command/AbstractCommandRunner.java

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
* #L%
2121
*/
2222

23+
import com.datastax.astra.client.Collection;
2324
import com.datastax.astra.client.DataAPIOptions;
2425
import com.datastax.astra.internal.http.RetryHttpClient;
2526
import com.datastax.astra.internal.api.ApiResponse;
@@ -34,7 +35,6 @@
3435
import java.util.Collections;
3536
import java.util.Map;
3637
import java.util.concurrent.CompletableFuture;
37-
import java.util.concurrent.CompletionStage;
3838
import java.util.concurrent.ConcurrentHashMap;
3939
import java.util.function.Consumer;
4040
import java.util.stream.Collectors;
@@ -111,13 +111,10 @@ public ApiResponse runCommand(Command command) {
111111
/**
112112
* Asynchronously send calls to listener for tracing.
113113
*
114-
* @param lambda
115-
* operations to execute
116-
* @return
117-
* the void object
114+
* @param lambda operations to execute
118115
*/
119-
private CompletionStage<Void> notifyASync(Consumer<CommandObserver> lambda) {
120-
return CompletableFutures.allDone(observers.values().stream()
116+
private void notifyASync(Consumer<CommandObserver> lambda) {
117+
CompletableFutures.allDone(observers.values().stream()
121118
.map(l -> CompletableFuture.runAsync(() -> lambda.accept(l)))
122119
.collect(Collectors.toList()));
123120
}

astra-db-java/src/main/java/com/datastax/astra/internal/utils/CustomEJsonCalendarDeserializer.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,9 @@ public CustomEJsonCalendarDeserializer() {
4545
public Calendar deserialize(JsonParser jp, DeserializationContext ctxt)
4646
throws IOException, JsonProcessingException {
4747
JsonNode node = jp.getCodec().readTree(jp);
48+
if (null == node.get("$date")) {
49+
throw new IllegalArgumentException("Cannot convert the expression as an Calendar " + node);
50+
}
4851
long timestamp = node.get("$date").asLong();
4952
Calendar calendar = Calendar.getInstance();
5053
calendar.setTimeInMillis(timestamp);

astra-db-java/src/main/java/com/datastax/astra/internal/utils/CustomEJsonDateDeserializer.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,9 @@ public CustomEJsonDateDeserializer() {
4545
public Date deserialize(JsonParser jp, DeserializationContext ctxt)
4646
throws IOException, JsonProcessingException {
4747
JsonNode node = jp.getCodec().readTree(jp);
48+
if (null == node.get("$date")) {
49+
throw new IllegalArgumentException("Cannot convert the expression as an Date " + node);
50+
}
4851
long timestamp = node.get("$date").asLong();
4952
return new Date(timestamp);
5053
}

astra-db-java/src/main/java/com/datastax/astra/internal/utils/CustomEJsonInstantDeserializer.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,9 @@ public CustomEJsonInstantDeserializer() {
4545
public Instant deserialize(JsonParser jp, DeserializationContext ctxt)
4646
throws IOException, JsonProcessingException {
4747
JsonNode node = jp.getCodec().readTree(jp);
48+
if (null == node.get("$date")) {
49+
throw new IllegalArgumentException("Cannot convert the expression as an Instant " + node);
50+
}
4851
long timestamp = node.get("$date").asLong();
4952
return Instant.ofEpochMilli(timestamp);
5053
}

astra-db-java/src/main/java/com/datastax/astra/internal/utils/CustomUuidDeserializer.java

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -45,8 +45,10 @@ public CustomUuidDeserializer() {
4545
public UUID deserialize(JsonParser jp, DeserializationContext ctxt)
4646
throws IOException, JsonProcessingException {
4747
JsonNode node = jp.getCodec().readTree(jp);
48-
String hexString = node.get("$uuid").asText();
49-
return UUID.fromString(hexString);
48+
if (null == node.get("$uuid")) {
49+
throw new IllegalArgumentException("Cannot convert the expression as an UUID " + node);
50+
}
51+
return UUID.fromString(node.get("$uuid").asText());
5052
}
5153

5254
}

0 commit comments

Comments
 (0)