Skip to content

Commit 3d69e41

Browse files
committed
Merge branch 'main' of github.com:hypertrace/document-store into bugfix_setSubDocOp
2 parents 8313386 + 9254122 commit 3d69e41

17 files changed

Lines changed: 1482 additions & 60 deletions

File tree

document-store/src/integrationTest/java/org/hypertrace/core/documentstore/MongoFlatPgConsistencyTest.java

Lines changed: 749 additions & 0 deletions
Large diffs are not rendered by default.

document-store/src/main/java/org/hypertrace/core/documentstore/TypesafeDatastoreConfigAdapter.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -94,7 +94,8 @@ public DatastoreConfig convert(final Config config) {
9494
connectionConfig.applicationName(),
9595
connectionConfig.connectionPoolConfig(),
9696
connectionConfig.queryTimeout(),
97-
connectionConfig.customParameters()) {
97+
connectionConfig.customParameters(),
98+
connectionConfig.collectionConfigs()) {
9899
@Override
99100
public String toConnectionString() {
100101
return config.hasPath("url")

document-store/src/main/java/org/hypertrace/core/documentstore/model/config/ConnectionConfig.java

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -75,12 +75,21 @@ public static class ConnectionConfigBuilder {
7575
String applicationName = DEFAULT_APP_NAME;
7676
String replicaSet;
7777
Map<String, String> customParameters = new HashMap<>();
78+
Map<String, org.hypertrace.core.documentstore.model.config.postgres.CollectionConfig>
79+
collectionConfigs = new HashMap<>();
7880

7981
public ConnectionConfigBuilder customParameter(String key, String value) {
8082
this.customParameters.put(key, value);
8183
return this;
8284
}
8385

86+
public ConnectionConfigBuilder collectionConfig(
87+
String collectionName,
88+
org.hypertrace.core.documentstore.model.config.postgres.CollectionConfig config) {
89+
this.collectionConfigs.put(collectionName, config);
90+
return this;
91+
}
92+
8493
ConnectionPoolConfig connectionPoolConfig;
8594
AggregatePipelineMode aggregationPipelineMode = AggregatePipelineMode.DEFAULT_ALWAYS;
8695
DataFreshness dataFreshness = DataFreshness.SYSTEM_DEFAULT;
@@ -127,7 +136,8 @@ public ConnectionConfig build() {
127136
applicationName,
128137
connectionPoolConfig,
129138
queryTimeout,
130-
customParameters);
139+
customParameters,
140+
collectionConfigs);
131141
}
132142

133143
throw new IllegalArgumentException("Unsupported database type: " + type);

document-store/src/main/java/org/hypertrace/core/documentstore/model/config/TypesafeConfigDatastoreConfigExtractor.java

Lines changed: 56 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,12 +10,14 @@
1010
import org.hypertrace.core.documentstore.model.config.ConnectionPoolConfig.ConnectionPoolConfigBuilder;
1111
import org.hypertrace.core.documentstore.model.config.DatastoreConfig.DatastoreConfigBuilder;
1212
import org.hypertrace.core.documentstore.model.config.Endpoint.EndpointBuilder;
13+
import org.hypertrace.core.documentstore.model.config.postgres.TimestampFieldsConfig;
1314
import org.hypertrace.core.documentstore.model.options.DataFreshness;
1415
import org.slf4j.Logger;
1516
import org.slf4j.LoggerFactory;
1617

1718
@Value
1819
public class TypesafeConfigDatastoreConfigExtractor {
20+
1921
private static final Logger LOGGER =
2022
LoggerFactory.getLogger(TypesafeConfigDatastoreConfigExtractor.class);
2123
private static final String DEFAULT_HOST_KEY = "host";
@@ -35,6 +37,10 @@ public class TypesafeConfigDatastoreConfigExtractor {
3537
private static final String DEFAULT_QUERY_TIMEOUT_KEY = "queryTimeout";
3638
private static final String DEFAULT_CONNECTION_TIMEOUT_KEY = "connectionTimeout";
3739
private static final String DEFAULT_CUSTOM_PARAMETERS_PREFIX = "customParams";
40+
private static final String DEFAULT_COLLECTION_CONFIGS_PREFIX = "collectionConfigs";
41+
private static final String TIMESTAMP_FIELDS_KEY = "timestampFields";
42+
private static final String TIMESTAMP_CREATED_KEY = "created";
43+
private static final String TIMESTAMP_LAST_UPDATED_KEY = "lastUpdated";
3844

3945
@NonNull Config config;
4046
DatastoreConfigBuilder datastoreConfigBuilder;
@@ -82,7 +88,8 @@ private TypesafeConfigDatastoreConfigExtractor(
8288
.dataFreshnessKey(DEFAULT_DATA_FRESHNESS_KEY)
8389
.queryTimeoutKey(DEFAULT_QUERY_TIMEOUT_KEY)
8490
.connectionTimeoutKey(DEFAULT_CONNECTION_TIMEOUT_KEY)
85-
.customParametersKey(DEFAULT_CUSTOM_PARAMETERS_PREFIX);
91+
.customParametersKey(DEFAULT_CUSTOM_PARAMETERS_PREFIX)
92+
.collectionConfigsKey(dataStoreType + "." + DEFAULT_COLLECTION_CONFIGS_PREFIX);
8693
}
8794

8895
public static TypesafeConfigDatastoreConfigExtractor from(
@@ -253,6 +260,53 @@ public TypesafeConfigDatastoreConfigExtractor connectionTimeoutKey(@NonNull fina
253260
return this;
254261
}
255262

263+
public TypesafeConfigDatastoreConfigExtractor collectionConfigsKey(@NonNull final String key) {
264+
if (!config.hasPath(key)) {
265+
return this;
266+
}
267+
268+
try {
269+
Config collectionsConfig = config.getConfig(key);
270+
collectionsConfig
271+
.root()
272+
.keySet()
273+
.forEach(
274+
collectionName -> {
275+
Config collectionConfig = collectionsConfig.getConfig(collectionName);
276+
org.hypertrace.core.documentstore.model.config.postgres.CollectionConfig
277+
.CollectionConfigBuilder
278+
builder =
279+
org.hypertrace.core.documentstore.model.config.postgres.CollectionConfig
280+
.builder();
281+
282+
if (collectionConfig.hasPath(TIMESTAMP_FIELDS_KEY)) {
283+
builder.timestampFields(
284+
parseTimestampFieldsConfig(collectionConfig.getConfig(TIMESTAMP_FIELDS_KEY)));
285+
}
286+
287+
connectionConfigBuilder.collectionConfig(collectionName, builder.build());
288+
});
289+
} catch (Exception e) {
290+
LOGGER.warn(
291+
"Collection configs key '{}' exists but could not be parsed: {}", key, e.getMessage());
292+
}
293+
294+
return this;
295+
}
296+
297+
private TimestampFieldsConfig parseTimestampFieldsConfig(Config timestampConfig) {
298+
TimestampFieldsConfig.TimestampFieldsConfigBuilder tsBuilder = TimestampFieldsConfig.builder();
299+
300+
if (timestampConfig.hasPath(TIMESTAMP_CREATED_KEY)) {
301+
tsBuilder.created(timestampConfig.getString(TIMESTAMP_CREATED_KEY));
302+
}
303+
if (timestampConfig.hasPath(TIMESTAMP_LAST_UPDATED_KEY)) {
304+
tsBuilder.lastUpdated(timestampConfig.getString(TIMESTAMP_LAST_UPDATED_KEY));
305+
}
306+
307+
return tsBuilder.build();
308+
}
309+
256310
public DatastoreConfig extract() {
257311
if (connectionConfigBuilder.endpoints().isEmpty()
258312
&& !Endpoint.builder().build().equals(endpointBuilder.build())) {
@@ -265,6 +319,7 @@ public DatastoreConfig extract() {
265319
.connectionPoolConfig(connectionPoolConfigBuilder.build())
266320
.credentials(connectionCredentialsBuilder.build())
267321
.customParameters(connectionConfigBuilder.customParameters())
322+
.collectionConfigs(connectionConfigBuilder.collectionConfigs())
268323
.build())
269324
.build();
270325
}
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
package org.hypertrace.core.documentstore.model.config.postgres;
2+
3+
import java.util.Optional;
4+
import javax.annotation.Nullable;
5+
import lombok.Builder;
6+
import lombok.Value;
7+
8+
@Value
9+
@Builder
10+
public class CollectionConfig {
11+
12+
/** Timestamp field configuration for auto-managed created/updated timestamps */
13+
@Nullable TimestampFieldsConfig timestampFields;
14+
15+
public Optional<TimestampFieldsConfig> getTimestampFields() {
16+
return Optional.ofNullable(timestampFields);
17+
}
18+
19+
public static CollectionConfig empty() {
20+
return CollectionConfig.builder().build();
21+
}
22+
}

document-store/src/main/java/org/hypertrace/core/documentstore/model/config/postgres/PostgresConnectionConfig.java

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55

66
import java.time.Duration;
77
import java.util.ArrayList;
8+
import java.util.Collections;
89
import java.util.List;
910
import java.util.Map;
1011
import java.util.Optional;
@@ -46,6 +47,7 @@ public class PostgresConnectionConfig extends ConnectionConfig {
4647
@NonNull Duration queryTimeout;
4748
@NonNull Duration schemaCacheExpiry;
4849
@NonNull Duration schemaRefreshCooldown;
50+
@NonNull Map<String, CollectionConfig> collectionConfigs;
4951

5052
public static ConnectionConfigBuilder builder() {
5153
return ConnectionConfig.builder().type(DatabaseType.POSTGRES);
@@ -58,7 +60,8 @@ public PostgresConnectionConfig(
5860
@NonNull final String applicationName,
5961
@Nullable final ConnectionPoolConfig connectionPoolConfig,
6062
@NonNull final Duration queryTimeout,
61-
@NonNull final Map<String, String> customParameters) {
63+
@NonNull final Map<String, String> customParameters,
64+
@Nullable final Map<String, CollectionConfig> collectionConfigs) {
6265
super(
6366
ensureSingleEndpoint(endpoints),
6467
getDatabaseOrDefault(database),
@@ -69,6 +72,7 @@ public PostgresConnectionConfig(
6972
this.queryTimeout = queryTimeout;
7073
this.schemaCacheExpiry = extractSchemaCacheExpiry(customParameters);
7174
this.schemaRefreshCooldown = extractSchemaRefreshCooldown(customParameters);
75+
this.collectionConfigs = collectionConfigs != null ? collectionConfigs : Collections.emptyMap();
7276
}
7377

7478
public String toConnectionString() {
@@ -157,4 +161,8 @@ private static Duration extractSchemaRefreshCooldown(final Map<String, String> c
157161
.map(Duration::ofMillis)
158162
.orElse(DEFAULT_SCHEMA_REFRESH_COOLDOWN);
159163
}
164+
165+
public Optional<CollectionConfig> getCollectionConfig(String collectionName) {
166+
return Optional.ofNullable(collectionConfigs.get(collectionName));
167+
}
160168
}
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
package org.hypertrace.core.documentstore.model.config.postgres;
2+
3+
import java.util.Optional;
4+
import javax.annotation.Nullable;
5+
import lombok.Builder;
6+
import lombok.Value;
7+
8+
/**
9+
* Configuration for auto-managed timestamp fields in a Postgres collection. Specifies which columns
10+
* should be automatically populated with creation and last update timestamps.
11+
*/
12+
@Value
13+
@Builder
14+
public class TimestampFieldsConfig {
15+
16+
/**
17+
* Column name for the creation timestamp. This field is set once when a document is created and
18+
* preserved on updates.
19+
*/
20+
@Nullable String created;
21+
22+
/**
23+
* Column name for the last update timestamp. This field is updated every time a document is
24+
* created or modified.
25+
*/
26+
@Nullable String lastUpdated;
27+
28+
public Optional<String> getCreated() {
29+
return Optional.ofNullable(created);
30+
}
31+
32+
public Optional<String> getLastUpdated() {
33+
return Optional.ofNullable(lastUpdated);
34+
}
35+
}

0 commit comments

Comments
 (0)