Skip to content
Draft
570 changes: 0 additions & 570 deletions src/main/java/edu/harvard/iq/dataverse/export/ExportService.java

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
package edu.harvard.iq.dataverse.export.service;

import edu.harvard.iq.dataverse.Dataset;
import io.gdcc.spi.export.ExportException;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.Optional;

/**
* Storage abstraction for cached metadata exports. Implementations own all
* knowledge about where and under which names cached exports live; the export
* pipeline only ever deals in {@link ExportCacheKey}s and streams.
*/
public sealed interface ExportCache permits StorageIOCache {

/**
* Looks up a cached export.
* @return the cached export stream, or empty if none is cached. Note: the caller is responsible for closing the stream.
* @throws IOException on actual storage failures (not on a cache miss)
*/
Optional<InputStream> read(ExportCacheKey key) throws IOException;

/**
* Produces and stores an export. The {@code writer} callback receives the output stream to write to.
* Any implementations guarantee that a partially written export is never made visible under the cache key
* (i.e., a failed write leaves either the previous entry or no entry).
*/
void write(ExportCacheKey key, ExportStreamWriter writer) throws ExportException, IOException;

/** Removes a cached export. Absence of the entry is not an error. */
void evict(ExportCacheKey key) throws IOException;

/**
* Removes all cached exports for a dataset, across all versions and formats, including legacy (pre-versioning) entries.
* Intended for publish/deaccession hooks and the admin "reexport" API.
*/
void evictAll(Dataset dataset) throws IOException;

/** Callback that renders an export into the store-provided stream. */
@FunctionalInterface
interface ExportStreamWriter {
void writeTo(OutputStream out) throws ExportException, IOException;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
package edu.harvard.iq.dataverse.export.service;

import java.util.List;

/**
* Represents an abstraction for determining whether a cached export needs to be invalidated and regenerated.
* <p>
* This sealed interface is intended to enforce a controlled hierarchy of classes that implement the cache
* invalidation logic, ensuring behavior consistency across different implementations. If necessary, the contract
* may be altered to allow more dynamic discovery of invalidators.
*/
public sealed interface ExportCacheInvalidator permits FileEmbargoExpiryInvalidator {

/**
* A collection of {@link ExportCacheInvalidator} instances.
* This list is intended to centralize all invalidation mechanisms for export cache entries.
* Any new implementations must be added here in addition to the "permits" on the interface seal.
*/
List<ExportCacheInvalidator> invalidators = List.of(new FileEmbargoExpiryInvalidator());

/** Should a cached export for this key be discarded and regenerated? */
boolean isStale(ExportCacheKey key);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
package edu.harvard.iq.dataverse.export.service;

import edu.harvard.iq.dataverse.Dataset;
import edu.harvard.iq.dataverse.DatasetVersion;

import java.util.Objects;

/**
* This record encapsulates information related to the dataset, the version of the dataset,
* and the format name used for the export, enabling precise identification
* of cache entries for export operations.
*/
public record ExportCacheKey(Dataset dataset, DatasetVersion version, String formatName) {

/**
* Constructs an ExportCacheKey instance with the specified dataset, dataset version, and format name.
* @param dataset the dataset associated with this cache key; must not be null
* @param version the dataset version associated with this cache key; must not be null
* @param formatName the format name used for export operations; must not be null or blank
* @throws NullPointerException if the dataset, version, or formatName is null
* @throws IllegalArgumentException if the formatName is blank or empty
*/
public ExportCacheKey(Dataset dataset, DatasetVersion version, String formatName) {
this.dataset = Objects.requireNonNull(dataset);
this.version = Objects.requireNonNull(version);
if (Objects.requireNonNull(formatName).isBlank()) {
throw new IllegalArgumentException("formatName must not be blank or empty");
}
this.formatName = formatName;
}

/**
* Convenience wrapper to create a cache key fro ma version and format alone.
* Note: the entity object must have a reference to the dataset present!
* @param version the dataset version
* @param formatName the target format
* @throws NullPointerException if either version, the dataset in the version or the format are null
* @throws IllegalArgumentException if the format name is blank or empty
*/
public ExportCacheKey(DatasetVersion version, String formatName) {
this(Objects.requireNonNull(version).getDataset(), version, formatName);
}

/** The one canonical, version-qualified aux tag. */
public String auxTag() {
return "export_" + formatName + "_" + version.getFriendlyVersionNumber() + ".cached";
}
}
Loading
Loading