Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Expose Nessie repository information (preparation) #6635

Merged
merged 1 commit into from
Apr 21, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
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.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: was 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;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: This can pprobably be in #6640

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