Skip to content

Commit

Permalink
Expose Nessie repository information (preparation)
Browse files Browse the repository at this point in the history
Enhances the REST endpoint `v2/config` with repository specific information:
* repository creation timestamp (new storage model only)
* oldest possible commit timestamp (new storage model only)
* no-ancestor-hash value
* default branch name (currently hard-wired to the configuration value)

Prepares the API changes for #4993 and #5810.

Since this changes the existing model for v2-beta, the added fields will
be populated in a follow-up-PR.
  • Loading branch information
snazy committed Apr 20, 2023
1 parent f0d3937 commit b5bed0d
Show file tree
Hide file tree
Showing 12 changed files with 207 additions and 8 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -15,15 +15,27 @@
*/
package org.projectnessie.model;

import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.JsonInclude.Include;
import com.fasterxml.jackson.annotation.JsonView;
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import java.time.Instant;
import java.util.Map;
import javax.annotation.Nullable;
import javax.validation.constraints.Size;
import org.eclipse.microprofile.openapi.annotations.enums.SchemaType;
import org.eclipse.microprofile.openapi.annotations.media.Schema;
import org.immutables.value.Value;
import org.projectnessie.model.CommitMeta.InstantDeserializer;
import org.projectnessie.model.CommitMeta.InstantSerializer;
import org.projectnessie.model.ser.Views;

/** configuration object to tell a client how a server is configured. */
@Schema(
type = SchemaType.OBJECT,
title = "NessieConfiguration",
description = "Configuration object to tell a client how a server is configured.")
@Value.Immutable
@JsonSerialize(as = ImmutableNessieConfiguration.class)
@JsonDeserialize(as = ImmutableNessieConfiguration.class)
Expand Down Expand Up @@ -57,11 +69,57 @@ public int getMinSupportedApiVersion() {
*/
public abstract int getMaxSupportedApiVersion();

/** Semver version representing the behavior of the Nessie server. */
@JsonView(Views.V2.class)
@Nullable
@jakarta.annotation.Nullable
public abstract String getSpecVersion();

/**
* The so called no-ancestor-hash defines the commit-ID of the "beginning of time" in the
* repository. The very first commit will have the value returned by this function as its parent
* commit-ID. A commit with this value does never exist.
*/
@JsonView(Views.V2.class)
@JsonInclude(Include.NON_NULL)
@Nullable
@jakarta.annotation.Nullable
public abstract String getNoAncestorHash();

/**
* Timestamp when the repository has been created.
*
* <p>The value is only returned, if the server supports this attribute.
*/
@JsonView(Views.V2.class)
@JsonInclude(Include.NON_NULL)
@Nullable
@jakarta.annotation.Nullable
@JsonSerialize(using = InstantSerializer.class)
@JsonDeserialize(using = InstantDeserializer.class)
public abstract Instant getRepositoryCreationTimestamp();

/**
* Timestamp of the oldest possible commit in the repository.
*
* <p>For new repositories, this is likely the same as {@link #getRepositoryCreationTimestamp()}.
* For imported repositories, this shall be the timestamp of the oldest commit.
*
* <p>The value is only returned, if the server supports this attribute.
*/
@JsonView(Views.V2.class)
@JsonInclude(Include.NON_NULL)
@Nullable
@jakarta.annotation.Nullable
@JsonSerialize(using = InstantSerializer.class)
@JsonDeserialize(using = InstantDeserializer.class)
public abstract Instant getOldestPossibleCommitTimestamp();

/** Additional properties, currently undefined and always empty (not present in JSON). */
@JsonView(Views.V2.class)
@JsonInclude(Include.NON_EMPTY)
public abstract Map<String, String> getAdditionalProperties();

public static NessieConfiguration getBuiltInConfig() {
return NessieConfigurationHolder.NESSIE_API_SPEC;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,18 +19,19 @@
import javax.inject.Inject;
import org.projectnessie.services.config.ServerConfig;
import org.projectnessie.services.impl.ConfigApiImpl;
import org.projectnessie.versioned.VersionStore;

@ApplicationScoped
@jakarta.enterprise.context.ApplicationScoped
public class RestConfigService extends ConfigApiImpl {
// Mandated by CDI 2.0
public RestConfigService() {
this(null);
this(null, null);
}

@Inject
@jakarta.inject.Inject
public RestConfigService(ServerConfig config) {
super(config);
public RestConfigService(ServerConfig config, VersionStore store) {
super(config, store);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
import org.projectnessie.model.ser.Views;
import org.projectnessie.services.config.ServerConfig;
import org.projectnessie.services.impl.ConfigApiImpl;
import org.projectnessie.versioned.VersionStore;

/** REST endpoint to retrieve server settings. */
@RequestScoped
Expand All @@ -33,13 +34,13 @@ public class RestV2ConfigResource implements HttpConfigApi {

// Mandated by CDI 2.0
public RestV2ConfigResource() {
this(null);
this(null, null);
}

@Inject
@jakarta.inject.Inject
public RestV2ConfigResource(ServerConfig config) {
this.config = new ConfigApiImpl(config);
public RestV2ConfigResource(ServerConfig config, VersionStore store) {
this.config = new ConfigApiImpl(config, store);
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,12 +19,15 @@
import org.projectnessie.model.NessieConfiguration;
import org.projectnessie.services.config.ServerConfig;
import org.projectnessie.services.spi.ConfigService;
import org.projectnessie.versioned.VersionStore;

public class ConfigApiImpl implements ConfigService {

private final VersionStore store;
private final ServerConfig config;

public ConfigApiImpl(ServerConfig config) {
public ConfigApiImpl(ServerConfig config, VersionStore store) {
this.store = store;
this.config = config;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,9 +30,23 @@
import org.projectnessie.model.NessieConfiguration;
import org.projectnessie.model.Operation.Put;
import org.projectnessie.model.Operation.Unchanged;
import org.projectnessie.versioned.RepositoryInformation;

public abstract class AbstractTestMisc extends BaseTestServiceImpl {

@Test
public void testRepositoryInformation() {
RepositoryInformation info = versionStore().getRepositoryInformation();
soft.assertThat(info).isNotNull();
soft.assertThat(info.getNoAncestorHash())
.isNotNull()
.isEqualTo(versionStore().noAncestorHash().asString());
if (versionStore().getClass().getName().endsWith("VersionStoreImpl")) {
soft.assertThat(info.getRepositoryCreationTimestamp()).isNotNull();
soft.assertThat(info.getOldestPossibleCommitTimestamp()).isNotNull();
}
}

@Test
public void testSupportedApiVersions() {
NessieConfiguration serverConfig = configApi().getConfig();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -113,7 +113,7 @@ public boolean sendStacktraceToClient() {
private Principal principal;

protected final ConfigApiImpl configApi() {
return new ConfigApiImpl(config());
return new ConfigApiImpl(config(), versionStore());
}

protected final TreeApiImpl treeApi() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@
import org.projectnessie.versioned.ImmutableCommit;
import org.projectnessie.versioned.ImmutableMergeResult;
import org.projectnessie.versioned.ImmutableRefLogDetails;
import org.projectnessie.versioned.ImmutableRepositoryInformation;
import org.projectnessie.versioned.KeyEntry;
import org.projectnessie.versioned.MergeConflictException;
import org.projectnessie.versioned.MergeResult;
Expand All @@ -66,6 +67,7 @@
import org.projectnessie.versioned.ReferenceConflictException;
import org.projectnessie.versioned.ReferenceInfo;
import org.projectnessie.versioned.ReferenceNotFoundException;
import org.projectnessie.versioned.RepositoryInformation;
import org.projectnessie.versioned.StoreWorker;
import org.projectnessie.versioned.Unchanged;
import org.projectnessie.versioned.VersionStore;
Expand Down Expand Up @@ -99,6 +101,15 @@ public PersistVersionStore(DatabaseAdapter databaseAdapter) {
this.databaseAdapter = databaseAdapter;
}

@Nonnull
@jakarta.annotation.Nonnull
@Override
public RepositoryInformation getRepositoryInformation() {
return ImmutableRepositoryInformation.builder()
.noAncestorHash(noAncestorHash().asString())
.build();
}

@Override
public Hash hashOnReference(NamedRef namedReference, Optional<Hash> hashOnReference)
throws ReferenceNotFoundException {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
import java.util.Optional;
import java.util.concurrent.Callable;
import java.util.function.BiConsumer;
import java.util.function.Supplier;
import java.util.stream.Stream;
import javax.annotation.Nonnull;
import org.projectnessie.model.CommitMeta;
Expand Down Expand Up @@ -63,6 +64,13 @@ public MetricsVersionStore(VersionStore delegate) {
this(delegate, Metrics.globalRegistry, Clock.SYSTEM);
}

@Nonnull
@jakarta.annotation.Nonnull
@Override
public RepositoryInformation getRepositoryInformation() {
return delegate("repositoryInformation", delegate::getRepositoryInformation);
}

@Override
public Hash hashOnReference(NamedRef namedReference, Optional<Hash> hashOnReference)
throws ReferenceNotFoundException {
Expand Down Expand Up @@ -291,6 +299,14 @@ private <R, E extends VersionStoreException> Stream<R> delegateStream1Ex(
}
}

private <R> R delegate(String requestName, Supplier<R> delegate) {
try {
return delegate2ExR(requestName, delegate::get);
} catch (VersionStoreException e) {
throw new RuntimeException(e);
}
}

private <R, E1 extends VersionStoreException> R delegate1Ex(
String requestName, DelegateWith1<R, E1> delegate) throws E1 {
return delegate2ExR(requestName, delegate::handle);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
/*
* Copyright (C) 2023 Dremio
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.projectnessie.versioned;

import java.time.Instant;
import java.util.Map;
import javax.annotation.Nullable;
import org.immutables.value.Value;

/**
* Informational object to tell a client about the Nessie repository.
*
* <p>All values are optional and may or may not be present, depending on the actual server version.
*/
@Value.Immutable
public interface RepositoryInformation {
@Nullable
@jakarta.annotation.Nullable
String getDefaultBranch();

@Nullable
@jakarta.annotation.Nullable
String getNoAncestorHash();

@Nullable
@jakarta.annotation.Nullable
Instant getRepositoryCreationTimestamp();

@Nullable
@jakarta.annotation.Nullable
Instant getOldestPossibleCommitTimestamp();

Map<String, String> getAdditionalProperties();
}
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@
import java.util.concurrent.Callable;
import java.util.function.BiConsumer;
import java.util.function.Consumer;
import java.util.function.Supplier;
import java.util.stream.Stream;
import javax.annotation.Nonnull;
import org.projectnessie.model.CommitMeta;
Expand Down Expand Up @@ -75,6 +76,14 @@ public TracingVersionStore(VersionStore delegate) {
this.delegate = delegate;
}

@Nonnull
@jakarta.annotation.Nonnull
@Override
public RepositoryInformation getRepositoryInformation() {
return callWithNoException(
"RepositoryInformation", b -> {}, delegate::getRepositoryInformation);
}

@Override
public Hash hashOnReference(NamedRef namedReference, Optional<Hash> hashOnReference)
throws ReferenceNotFoundException {
Expand Down Expand Up @@ -316,6 +325,21 @@ private static <R, E1 extends VersionStoreException> PaginationIterator<R> callP
}
}

private static <R> R callWithNoException(
String spanName, Consumer<SpanBuilder> spanBuilder, Supplier<R> invoker) {
try (SpanHolder span = createSpan(spanName, spanBuilder);
Scope ignore = activeScope(span.get())) {
try {
return invoker.get();
} catch (IllegalArgumentException e) {
// IllegalArgumentException is a special kind of exception that indicates a user-error.
throw e;
} catch (RuntimeException e) {
throw traceError(span.get(), e);
}
}
}

private static <R, E1 extends VersionStoreException> R callWithOneException(
String spanName, Consumer<SpanBuilder> spanBuilder, InvokerWithOneException<R, E1> invoker)
throws E1 {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,10 @@
*/
public interface VersionStore {

@Nonnull
@jakarta.annotation.Nonnull
RepositoryInformation getRepositoryInformation();

/**
* Verifies that the given {@code namedReference} exists and that {@code hashOnReference}, if
* present, is reachable via that reference.
Expand Down

0 comments on commit b5bed0d

Please sign in to comment.