statements = new ArrayList<>();
+ // Nothing yet
+ return statements;
+ })
+ .build(pdm);
+
+ // TODO should not need to add as a table and an object. Get the table to add itself?
+ tbl.addTag(SCHEMA_GROUP_TAG, FHIRDATA_GROUP);
+ this.procedureDependencies.add(tbl);
+ pdm.addTable(tbl);
+ pdm.addObject(tbl);
+ }
+
/**
*
CREATE SEQUENCE fhir_sequence
diff --git a/fhir-persistence-schema/src/main/java/com/ibm/fhir/schema/control/FhirSchemaVersion.java b/fhir-persistence-schema/src/main/java/com/ibm/fhir/schema/control/FhirSchemaVersion.java
index e8233b8bf38..9800f8400f7 100644
--- a/fhir-persistence-schema/src/main/java/com/ibm/fhir/schema/control/FhirSchemaVersion.java
+++ b/fhir-persistence-schema/src/main/java/com/ibm/fhir/schema/control/FhirSchemaVersion.java
@@ -42,6 +42,8 @@ public enum FhirSchemaVersion {
,V0020(20, "issue-1834 Set PostgreSQL fillfactor", true)
,V0021(21, "issue-713 remove Resource_LOGICAL_RESOURCES, DomainResource_LOGICAL_RESOURCES tables", false)
,V0022(22, "issue-2979 stored procedure update for 2050 ifNoneMatch", false)
+ ,V0023(23, "issue-2900 erased_resources to support $erase when offloading payloads", false)
+ ,V0024(24, "issue-2900 for offloading add resource_payload_key to xx_resources", false)
;
// The version number recorded in the VERSION_HISTORY
diff --git a/fhir-persistence-schema/src/main/resources/db2/add_any_resource.sql b/fhir-persistence-schema/src/main/resources/db2/add_any_resource.sql
index e7713799f4a..4b392d1123d 100644
--- a/fhir-persistence-schema/src/main/resources/db2/add_any_resource.sql
+++ b/fhir-persistence-schema/src/main/resources/db2/add_any_resource.sql
@@ -38,11 +38,12 @@
IN p_last_updated TIMESTAMP,
IN p_is_deleted CHAR( 1),
IN p_version INT,
- IN p_parameter_hash_b64 VARCHAR(44 OCTETS),
+ IN p_parameter_hash_b64 VARCHAR( 44 OCTETS),
IN p_if_none_match INT,
+ IN p_resource_payload_key VARCHAR( 36 OCTETS),
OUT o_logical_resource_id BIGINT,
OUT o_resource_row_id BIGINT,
- OUT o_current_parameter_hash VARCHAR(44 OCTETS),
+ OUT o_current_parameter_hash VARCHAR( 44 OCTETS),
OUT o_interaction_status INT,
OUT o_if_none_match_version INT
)
@@ -168,9 +169,9 @@ BEGIN
END IF; -- end if existing resource
PREPARE stmt FROM
- 'INSERT INTO ' || v_schema_name || '.' || p_resource_type || '_resources (mt_id, resource_id, logical_resource_id, version_id, data, last_updated, is_deleted) '
- || ' VALUES ( ?, ?, ?, ?, ?, ?, ?)';
- EXECUTE stmt USING {{ADMIN_SCHEMA_NAME}}.sv_tenant_id, v_resource_id, v_logical_resource_id, p_version, p_payload, p_last_updated, p_is_deleted;
+ 'INSERT INTO ' || v_schema_name || '.' || p_resource_type || '_resources (mt_id, resource_id, logical_resource_id, version_id, data, last_updated, is_deleted, resource_payload_key) '
+ || ' VALUES ( ?, ?, ?, ?, ?, ?, ?, ?)';
+ EXECUTE stmt USING {{ADMIN_SCHEMA_NAME}}.sv_tenant_id, v_resource_id, v_logical_resource_id, p_version, p_payload, p_last_updated, p_is_deleted, p_resource_payload_key;
IF v_new_resource = 0 THEN
-- As this is an existing logical resource, we need to update the xx_logical_resource values to match
diff --git a/fhir-persistence-schema/src/main/resources/db2/erase_resource.sql b/fhir-persistence-schema/src/main/resources/db2/erase_resource.sql
index e926ad9e748..cda746a3026 100644
--- a/fhir-persistence-schema/src/main/resources/db2/erase_resource.sql
+++ b/fhir-persistence-schema/src/main/resources/db2/erase_resource.sql
@@ -13,6 +13,7 @@
-- ----------------------------------------------------------------------------
( IN p_resource_type VARCHAR( 36 OCTETS),
IN p_logical_id VARCHAR( 255 OCTETS),
+ IN p_erased_resource_group_id BIGINT,
OUT o_deleted BIGINT)
LANGUAGE SQL
MODIFIES SQL DATA
@@ -25,7 +26,7 @@ BEGIN
DECLARE v_not_found BIGINT DEFAULT 0;
DECLARE v_msg VARCHAR(128 OCTETS) DEFAULT 'DEFAULT ERROR';
- DECLARE r_stmt, dr_stmt, d_stmt, dlr_stmt, dglr_stmt, drcl_stmt STATEMENT;
+ DECLARE r_stmt, dr_stmt, d_stmt, dlr_stmt, dglr_stmt, drcl_stmt, iv_stmt STATEMENT;
-- Set a condition when the resource is not found.
DECLARE CONTINUE HANDLER FOR NOT FOUND SET v_not_found = -1;
@@ -54,6 +55,13 @@ BEGIN
|| ' WHERE LOGICAL_RESOURCE_ID = ?)';
EXECUTE rcl_stmt USING v_logical_resource_id;
+ -- Step 1.1: Record the versions we need to delete if we are doing payload offload
+ PREPARE iv_stmt FROM 'INSERT INTO {{SCHEMA_NAME}}.erased_resources(mt_id, erased_resource_group_id, resource_type_id, logical_id, version_id) '
+ || ' SELECT ?, ?, ?, ?, version_id '
+ || ' FROM {{SCHEMA_NAME}}.' || p_resource_type || '_RESOURCES '
+ || ' WHERE LOGICAL_RESOURCE_ID = ? ';
+ EXECUTE iv_stmt USING {{ADMIN_SCHEMA_NAME}}.sv_tenant_id, p_erased_resource_group_id, v_resource_type_id, p_logical_id, v_logical_resource_id;
+
-- Step 2: Delete All Versions from Resources Table
-- Create the prepared statement to delete Resource Versions in chunks
-- Implementation note: fetch must be the last part of the sub-select
diff --git a/fhir-persistence-schema/src/main/resources/postgres/add_any_resource.sql b/fhir-persistence-schema/src/main/resources/postgres/add_any_resource.sql
index 34d155789c4..652efa6393a 100644
--- a/fhir-persistence-schema/src/main/resources/postgres/add_any_resource.sql
+++ b/fhir-persistence-schema/src/main/resources/postgres/add_any_resource.sql
@@ -38,6 +38,7 @@
IN p_version INT,
IN p_parameter_hash_b64 VARCHAR( 44),
IN p_if_none_match INT,
+ IN p_resource_payload_key VARCHAR( 36),
OUT o_logical_resource_id BIGINT,
OUT o_current_parameter_hash VARCHAR( 44),
OUT o_interaction_status INT,
@@ -153,9 +154,9 @@ BEGIN
END IF; -- end if existing resource
EXECUTE
- 'INSERT INTO ' || v_schema_name || '.' || p_resource_type || '_resources (resource_id, logical_resource_id, version_id, data, last_updated, is_deleted) '
- || ' VALUES ($1, $2, $3, $4, $5, $6)'
- USING v_resource_id, v_logical_resource_id, p_version, p_payload, p_last_updated, p_is_deleted;
+ 'INSERT INTO ' || v_schema_name || '.' || p_resource_type || '_resources (resource_id, logical_resource_id, version_id, data, last_updated, is_deleted, resource_payload_key) '
+ || ' VALUES ($1, $2, $3, $4, $5, $6, $7)'
+ USING v_resource_id, v_logical_resource_id, p_version, p_payload, p_last_updated, p_is_deleted, p_resource_payload_key;
IF v_new_resource = 0 THEN
diff --git a/fhir-persistence-schema/src/main/resources/postgres/erase_resource.sql b/fhir-persistence-schema/src/main/resources/postgres/erase_resource.sql
index c74960a18df..b19939e98d7 100644
--- a/fhir-persistence-schema/src/main/resources/postgres/erase_resource.sql
+++ b/fhir-persistence-schema/src/main/resources/postgres/erase_resource.sql
@@ -13,6 +13,7 @@
-- ----------------------------------------------------------------------------
( IN p_resource_type VARCHAR( 36),
IN p_logical_id VARCHAR( 255),
+ IN p_erased_resource_group_id BIGINT,
OUT o_deleted BIGINT)
RETURNS BIGINT
LANGUAGE plpgsql
@@ -52,6 +53,13 @@ BEGIN
|| ' FROM {{SCHEMA_NAME}}.' || p_resource_type || '_RESOURCES'
|| ' WHERE LOGICAL_RESOURCE_ID = $1)'
USING v_logical_resource_id;
+
+ -- Step 1.1: Record the versions we need to delete if we are doing payload offload
+ EXECUTE 'INSERT INTO {{SCHEMA_NAME}}.erased_resources(erased_resource_group_id, resource_type_id, logical_id, version_id) '
+ || ' SELECT $1, $2, $3, version_id '
+ || ' FROM {{SCHEMA_NAME}}.' || p_resource_type || '_RESOURCES '
+ || ' WHERE LOGICAL_RESOURCE_ID = $4 '
+ USING p_erased_resource_group_id, v_resource_type_id, p_logical_id, v_logical_resource_id;
-- Step 2: Delete All Versions from Resources Table
EXECUTE 'DELETE FROM {{SCHEMA_NAME}}.' || p_resource_type || '_RESOURCES WHERE LOGICAL_RESOURCE_ID = $1'
diff --git a/fhir-persistence-schema/src/test/java/com/ibm/fhir/schema/derby/DerbyFhirDatabaseTest.java b/fhir-persistence-schema/src/test/java/com/ibm/fhir/schema/derby/DerbyFhirDatabaseTest.java
index 6032398d173..72520ea6d75 100644
--- a/fhir-persistence-schema/src/test/java/com/ibm/fhir/schema/derby/DerbyFhirDatabaseTest.java
+++ b/fhir-persistence-schema/src/test/java/com/ibm/fhir/schema/derby/DerbyFhirDatabaseTest.java
@@ -138,7 +138,7 @@ protected void checkDatabase(IConnectionProvider cp, String schemaName) throws S
// Check that we have the correct number of tables. This will need to be updated
// whenever tables, views or sequences are added or removed
- assertEquals(adapter.listSchemaObjects(schemaName).size(), 1917);
+ assertEquals(adapter.listSchemaObjects(schemaName).size(), 1918);
c.commit();
} catch (Throwable t) {
c.rollback();
diff --git a/fhir-persistence-schema/src/test/java/com/ibm/fhir/schema/derby/DerbySchemaVersionsTest.java b/fhir-persistence-schema/src/test/java/com/ibm/fhir/schema/derby/DerbySchemaVersionsTest.java
index 08563486861..e7fc877e8e7 100644
--- a/fhir-persistence-schema/src/test/java/com/ibm/fhir/schema/derby/DerbySchemaVersionsTest.java
+++ b/fhir-persistence-schema/src/test/java/com/ibm/fhir/schema/derby/DerbySchemaVersionsTest.java
@@ -52,7 +52,7 @@ public void test() throws Exception {
// Make sure we can correctly determine the latest schema version value
svm.updateSchemaVersion();
- assertEquals(svm.getVersionForSchema(), FhirSchemaVersion.V0022.vid());
+ assertEquals(svm.getVersionForSchema(), FhirSchemaVersion.V0024.vid());
assertTrue(svm.isLatestSchema());
}
diff --git a/fhir-persistence/src/main/java/com/ibm/fhir/persistence/FHIRPersistence.java b/fhir-persistence/src/main/java/com/ibm/fhir/persistence/FHIRPersistence.java
index 14770d9c156..a1b4e519a00 100644
--- a/fhir-persistence/src/main/java/com/ibm/fhir/persistence/FHIRPersistence.java
+++ b/fhir-persistence/src/main/java/com/ibm/fhir/persistence/FHIRPersistence.java
@@ -16,7 +16,7 @@
import com.ibm.fhir.persistence.erase.EraseDTO;
import com.ibm.fhir.persistence.exception.FHIRPersistenceException;
import com.ibm.fhir.persistence.exception.FHIRPersistenceNotSupportedException;
-import com.ibm.fhir.persistence.payload.PayloadKey;
+import com.ibm.fhir.persistence.payload.PayloadPersistenceResponse;
/**
* This interface defines the contract between the FHIR Server's REST API layer and the underlying
@@ -107,7 +107,13 @@ SingleResourceResult vread(FHIRPersistenceContext contex
/**
* Deletes the specified FHIR Resource from the datastore.
- *
+ *
+ * This implementation of delete is open to a race condition if an update and delete
+ * are issues at the same time. This API has been deprecated and replaced with
+ * {@link #deleteWithMeta(FHIRPersistenceContext, Resource)}
+ * following the new pattern where the resource is never modified by the persistence
+ * layer.
+ *
* @param context the FHIRPersistenceContext instance associated with the current request
* @param resourceType The type of FHIR Resource to be deleted.
* @param logicalId the logical id of the FHIR Resource to be deleted
@@ -115,10 +121,23 @@ SingleResourceResult vread(FHIRPersistenceContext contex
* an OperationOutcome with hints, warnings, or errors related to the interaction
* @throws FHIRPersistenceException
*/
+ @Deprecated
default SingleResourceResult delete(FHIRPersistenceContext context, Class resourceType, String logicalId) throws FHIRPersistenceException {
throw new FHIRPersistenceNotSupportedException("The 'delete' operation is not supported by this persistence implementation");
}
+ /**
+ * Deletes the FHIR resource from the datastore. The resource must be configured with the correct
+ * meta information because the persistence layer no longer makes any modifications to resources.
+ * @param
+ * @param context
+ * @param resource
+ * @throws FHIRPersistenceException
+ */
+ default void deleteWithMeta(FHIRPersistenceContext context, T resource) throws FHIRPersistenceException {
+ throw new FHIRPersistenceNotSupportedException("The 'delete' operation is not supported by this persistence implementation");
+ }
+
/**
* Retrieves all of the versions of the specified FHIR Resource.
*
@@ -199,6 +218,15 @@ default boolean isReindexSupported() {
return false;
}
+ /**
+ * Returns true iff the persistence layer implementation supports offloading and this has been
+ * configured for the tenant/datasource
+ * @return
+ */
+ default boolean isOffloadingSupported() {
+ return false;
+ }
+
/**
* Initiates reindexing for either a specified list of index IDs,
* or a randomly chosen resource. The number of resources processed is returned.
@@ -293,12 +321,14 @@ default ResourceEraseRecord erase(EraseDTO eraseDto) throws FHIRPersistenceExcep
* {@link Future} can be used to obtain the status of the operation. If the result
* is null, then the implementation does not support offloading and the payload must
* be stored in the traditional manner (e.g. in the RDBMS). A {@link Future} is used
- * because the offloading storage operation may be asynchronous.
+ * because the offloading storage operation may be asynchronous. This Future must be
+ * resolved prior to the transaction commit.
* @param resource
* @param logicalId
* @param newVersionNumber
+ * @param resourcePayloadKey
* @return
* @throws FHIRPersistenceException
*/
- Future storePayload(Resource resource, String logicalId, int newVersionNumber) throws FHIRPersistenceException;
+ PayloadPersistenceResponse storePayload(Resource resource, String logicalId, int newVersionNumber, String resourcePayloadKey) throws FHIRPersistenceException;
}
\ No newline at end of file
diff --git a/fhir-persistence/src/main/java/com/ibm/fhir/persistence/payload/PayloadPersistenceHelper.java b/fhir-persistence/src/main/java/com/ibm/fhir/persistence/FHIRPersistenceSupport.java
similarity index 60%
rename from fhir-persistence/src/main/java/com/ibm/fhir/persistence/payload/PayloadPersistenceHelper.java
rename to fhir-persistence/src/main/java/com/ibm/fhir/persistence/FHIRPersistenceSupport.java
index fff62226c46..06119a819c7 100644
--- a/fhir-persistence/src/main/java/com/ibm/fhir/persistence/payload/PayloadPersistenceHelper.java
+++ b/fhir-persistence/src/main/java/com/ibm/fhir/persistence/FHIRPersistenceSupport.java
@@ -4,7 +4,7 @@
* SPDX-License-Identifier: Apache-2.0
*/
-package com.ibm.fhir.persistence.payload;
+package com.ibm.fhir.persistence;
import java.io.IOException;
import java.io.InputStream;
@@ -12,6 +12,7 @@
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
+import java.util.zip.GZIPInputStream;
import java.util.zip.GZIPOutputStream;
import com.ibm.fhir.model.format.Format;
@@ -29,9 +30,9 @@
/**
* Collection of helper methods related to the persistence of FHIR resource payload data
*/
-public class PayloadPersistenceHelper {
+public class FHIRPersistenceSupport {
// the logger to use for this class
- private static final Logger logger = Logger.getLogger(PayloadPersistenceHelper.class.getName());
+ private static final Logger logger = Logger.getLogger(FHIRPersistenceSupport.class.getName());
// initial buffer size for rendered payload
private static final int DATA_BUFFER_INITIAL_SIZE = 10*1024; // 10KiB
@@ -42,24 +43,23 @@ public class PayloadPersistenceHelper {
* @param compress
* @return
*/
- public static InputOutputByteStream render(Resource resource, boolean compress) throws FHIRPersistenceException {
+ public static InputOutputByteStream render(Resource resource, boolean compress) throws FHIRGeneratorException, IOException {
InputOutputByteStream ioStream = new InputOutputByteStream(DATA_BUFFER_INITIAL_SIZE);
if (compress) {
try (GZIPOutputStream zipStream = new GZIPOutputStream(ioStream.outputStream())) {
FHIRGenerator.generator(Format.JSON, false).generate(resource, zipStream);
- zipStream.close();
} catch (IOException | FHIRGeneratorException x) {
- logger.log(Level.SEVERE, "Resource: '" + resource.getClass().getSimpleName() + "/" + resource.getId() + "'", x);
- throw new FHIRPersistenceException("Store payload failed");
+ logger.log(Level.SEVERE, "Failed generating resource: '" + resource.getClass().getSimpleName() + "/" + resource.getId() + "'", x);
+ throw x;
}
} else {
// not compressed, so render directly to the ioStream
try {
FHIRGenerator.generator(Format.JSON, false).generate(resource, ioStream.outputStream());
} catch (FHIRGeneratorException x) {
- logger.log(Level.SEVERE, "Resource: '" + resource.getClass().getSimpleName() + "/" + resource.getId() + "'", x);
- throw new FHIRPersistenceException("Store payload failed");
+ logger.log(Level.SEVERE, "Failed generating resource: '" + resource.getClass().getSimpleName() + "/" + resource.getId() + "'", x);
+ throw x;
}
}
return ioStream;
@@ -71,12 +71,17 @@ public static InputOutputByteStream render(Resource resource, boolean compress)
* @param resourceType
* @param in
* @param elements
+ * @param uncompress
* @return
*/
- public static T parse(Class resourceType, InputStream in, List elements) {
+ public static T parse(Class resourceType, InputStream in, List elements, boolean uncompress) throws FHIRParserException, IOException {
T result;
-
try {
+ if (uncompress) {
+ // Wrap the InputStream so we uncompress the content when reading...and
+ // see we close the stream as required in the finally block
+ in = new GZIPInputStream(in);
+ }
if (elements != null) {
// parse/filter the resource using elements
result = FHIRParser.parser(Format.JSON).as(FHIRJsonParser.class).parseAndFilter(in, elements);
@@ -87,9 +92,11 @@ public static T parse(Class resourceType, InputStream in
} else {
result = FHIRParser.parser(Format.JSON).parse(in);
}
- } catch (FHIRParserException x) {
- // need to wrap because this method is being called as a lambda
- throw new RuntimeException(x);
+ } finally {
+ if (uncompress) {
+ // make sure we always close the GZIPInputStream to avoid leaking resources it holds onto
+ in.close();
+ }
}
return result;
@@ -102,4 +109,25 @@ public static T parse(Class resourceType, InputStream in
public static com.ibm.fhir.model.type.Instant getCurrentInstant() {
return com.ibm.fhir.model.type.Instant.now(ZoneOffset.UTC);
}
+
+ /**
+ * Obtain the versionId value from the Resource meta element, converting
+ * to an int for use by the persistence layer
+ * @param resource
+ * @return
+ * @throws FHIRPersistenceException
+ */
+ public static int getMetaVersionId(Resource resource) throws FHIRPersistenceException {
+ // Programming error if this is being called before the meta element has been set
+ // properly on the resource
+ if (resource.getMeta() == null || resource.getMeta().getVersionId() == null) {
+ throw new FHIRPersistenceException("Resource missing meta versionId");
+ }
+
+ String versionIdValue = resource.getMeta().getVersionId().getValue();
+ if (versionIdValue == null) {
+ throw new FHIRPersistenceException("Resource missing meta versionId value");
+ }
+ return Integer.parseInt(versionIdValue);
+ }
}
\ No newline at end of file
diff --git a/fhir-persistence/src/main/java/com/ibm/fhir/persistence/context/FHIRPersistenceContext.java b/fhir-persistence/src/main/java/com/ibm/fhir/persistence/context/FHIRPersistenceContext.java
index 045d9356ce5..d618e3cf24a 100644
--- a/fhir-persistence/src/main/java/com/ibm/fhir/persistence/context/FHIRPersistenceContext.java
+++ b/fhir-persistence/src/main/java/com/ibm/fhir/persistence/context/FHIRPersistenceContext.java
@@ -6,6 +6,7 @@
package com.ibm.fhir.persistence.context;
+import com.ibm.fhir.persistence.payload.PayloadPersistenceResponse;
import com.ibm.fhir.search.context.FHIRSearchContext;
/**
@@ -47,4 +48,10 @@ public interface FHIRPersistenceContext {
* @return the value from the If-None-Match header in the PUT request
*/
Integer getIfNoneMatch();
+
+ /**
+ * Get the payload persistence response
+ * @return
+ */
+ PayloadPersistenceResponse getOffloadResponse();
}
\ No newline at end of file
diff --git a/fhir-persistence/src/main/java/com/ibm/fhir/persistence/context/FHIRPersistenceContextFactory.java b/fhir-persistence/src/main/java/com/ibm/fhir/persistence/context/FHIRPersistenceContextFactory.java
index 57730585003..836acc15289 100644
--- a/fhir-persistence/src/main/java/com/ibm/fhir/persistence/context/FHIRPersistenceContextFactory.java
+++ b/fhir-persistence/src/main/java/com/ibm/fhir/persistence/context/FHIRPersistenceContextFactory.java
@@ -30,7 +30,8 @@ private FHIRPersistenceContextFactory() {
* @param event the FHIRPersistenceEvent instance to be contained in the FHIRPersistenceContext instance
*/
public static FHIRPersistenceContext createPersistenceContext(FHIRPersistenceEvent event) {
- return new FHIRPersistenceContextImpl(event);
+ return FHIRPersistenceContextImpl.builder(event)
+ .build();
}
/**
@@ -39,16 +40,20 @@ public static FHIRPersistenceContext createPersistenceContext(FHIRPersistenceEve
* @param includeDeleted flag to tell the persistence layer to include deleted resources in the operation results.
*/
public static FHIRPersistenceContext createPersistenceContext(FHIRPersistenceEvent event, boolean includeDeleted) {
- return new FHIRPersistenceContextImpl(event, includeDeleted);
+ return FHIRPersistenceContextImpl.builder(event)
+ .withIncludeDeleted(includeDeleted)
+ .build();
}
/**
* Returns a FHIRPersistenceContext that contains a FHIRPersistenceEvent instance.
* @param event the FHIRPersistenceEvent instance to be contained in the FHIRPersistenceContext instance
- * @param ifNoneExist flag to tell the persistence layer to apply conditional create-on-update logic.
+ * @param ifNoneMatch flag to tell the persistence layer to apply conditional create-on-update logic.
*/
- public static FHIRPersistenceContext createPersistenceContext(FHIRPersistenceEvent event, Integer ifNoneExist) {
- return new FHIRPersistenceContextImpl(event, ifNoneExist);
+ public static FHIRPersistenceContext createPersistenceContext(FHIRPersistenceEvent event, Integer ifNoneMatch) {
+ return FHIRPersistenceContextImpl.builder(event)
+ .withIfNoneMatch(ifNoneMatch)
+ .build();
}
/**
@@ -57,7 +62,9 @@ public static FHIRPersistenceContext createPersistenceContext(FHIRPersistenceEve
* @param historyContext the FHIRHistoryContext instance to be contained in the FHIRPersistenceContext instance
*/
public static FHIRPersistenceContext createPersistenceContext(FHIRPersistenceEvent event, FHIRHistoryContext historyContext) {
- return new FHIRPersistenceContextImpl(event, historyContext);
+ return FHIRPersistenceContextImpl.builder(event)
+ .withHistoryContext(historyContext)
+ .build();
}
/**
@@ -66,7 +73,9 @@ public static FHIRPersistenceContext createPersistenceContext(FHIRPersistenceEve
* @param searchContext the FHIRSearchContext instance to be contained in the FHIRPersistenceContext instance
*/
public static FHIRPersistenceContext createPersistenceContext(FHIRPersistenceEvent event, FHIRSearchContext searchContext) {
- return new FHIRPersistenceContextImpl(event, searchContext);
+ return FHIRPersistenceContextImpl.builder(event)
+ .withSearchContext(searchContext)
+ .build();
}
/**
@@ -96,6 +105,9 @@ public static FHIRHistoryContext createHistoryContext() {
* @param searchContext the FHIRSearchContext instance to be contained in the FHIRPersistenceContext instance
*/
public static FHIRPersistenceContext createPersistenceContext(FHIRPersistenceEvent event, boolean includeDeleted, FHIRSearchContext searchContext) {
- return new FHIRPersistenceContextImpl(event, includeDeleted, searchContext);
+ return FHIRPersistenceContextImpl.builder(event)
+ .withIncludeDeleted(includeDeleted)
+ .withSearchContext(searchContext)
+ .build();
}
}
diff --git a/fhir-persistence/src/main/java/com/ibm/fhir/persistence/context/impl/FHIRPersistenceContextImpl.java b/fhir-persistence/src/main/java/com/ibm/fhir/persistence/context/impl/FHIRPersistenceContextImpl.java
index f7bf9d90b72..db7b8f761c4 100644
--- a/fhir-persistence/src/main/java/com/ibm/fhir/persistence/context/impl/FHIRPersistenceContextImpl.java
+++ b/fhir-persistence/src/main/java/com/ibm/fhir/persistence/context/impl/FHIRPersistenceContextImpl.java
@@ -9,6 +9,7 @@
import com.ibm.fhir.persistence.context.FHIRHistoryContext;
import com.ibm.fhir.persistence.context.FHIRPersistenceContext;
import com.ibm.fhir.persistence.context.FHIRPersistenceEvent;
+import com.ibm.fhir.persistence.payload.PayloadPersistenceResponse;
import com.ibm.fhir.search.context.FHIRSearchContext;
/**
@@ -22,12 +23,119 @@ public class FHIRPersistenceContextImpl implements FHIRPersistenceContext {
private FHIRSearchContext searchContext;
private boolean includeDeleted = false;
private Integer ifNoneMatch;
+
+ // The response from the payload persistence (offloading) call, if any
+ private PayloadPersistenceResponse offloadResponse;
+
+ /**
+ * Factory function to create a FHIRPersistenceContext builder
+ * @param event
+ * @return
+ */
+ public static Builder builder(FHIRPersistenceEvent event) {
+ return new Builder(event);
+ }
+
+ /**
+ * Builder to create new instances of FHIRPersistenceContextImpl
+ */
+ public static class Builder {
+ private FHIRPersistenceEvent persistenceEvent;
+ private FHIRHistoryContext historyContext;
+ private FHIRSearchContext searchContext;
+ private boolean includeDeleted;
+ private Integer ifNoneMatch;
+ private PayloadPersistenceResponse offloadResponse;
+
+ /**
+ * Protected constructor
+ * @param event
+ */
+ protected Builder(FHIRPersistenceEvent event) {
+ this.persistenceEvent = event;
+ }
+
+ /**
+ * Build the FHIRPersistenceContext implementation
+ * @return
+ */
+ public FHIRPersistenceContext build() {
+ FHIRPersistenceContextImpl impl;
+
+ if (historyContext != null) {
+ impl = new FHIRPersistenceContextImpl(persistenceEvent, historyContext);
+ } else if (searchContext != null) {
+ impl = new FHIRPersistenceContextImpl(persistenceEvent, searchContext);
+ } else {
+ impl = new FHIRPersistenceContextImpl(persistenceEvent);
+ }
+ impl.setIfNoneMatch(ifNoneMatch);
+ impl.setIncludeDeleted(includeDeleted);
+ impl.setOffloadResponse(offloadResponse);
+
+ return impl;
+ }
+
+ /**
+ * Build with the given searchContext
+ * @param searchContext
+ * @return
+ */
+ public Builder withSearchContext(FHIRSearchContext searchContext) {
+ this.searchContext = searchContext;
+ return this;
+ }
+
+ /**
+ * Build with the given historyContext
+ * @param historyContext
+ * @return
+ */
+ public Builder withHistoryContext(FHIRHistoryContext historyContext) {
+ this.historyContext = historyContext;
+ return this;
+ }
- public FHIRPersistenceContextImpl(FHIRPersistenceEvent pe) {
+ /**
+ * Build with the ifNoneMatch value
+ * @param ifNoneMatch
+ * @return
+ */
+ public Builder withIfNoneMatch(Integer ifNoneMatch) {
+ this.ifNoneMatch = ifNoneMatch;
+ return this;
+ }
+
+ /**
+ * Build with the includeDeleted value
+ * @param includeDeleted
+ * @return
+ */
+ public Builder withIncludeDeleted(boolean includeDeleted) {
+ this.includeDeleted = includeDeleted;
+ return this;
+ }
+
+ /**
+ * Build with the given offloadResponse
+ * @param offloadResponse
+ * @return
+ */
+ public Builder withOffloadResponse(PayloadPersistenceResponse offloadResponse) {
+ this.offloadResponse = offloadResponse;
+ return this;
+ }
+ }
+
+ /**
+ * Private constructor
+ * @param pe
+ */
+ private FHIRPersistenceContextImpl(FHIRPersistenceEvent pe) {
this.persistenceEvent = pe;
}
- public FHIRPersistenceContextImpl(FHIRPersistenceEvent pe, boolean includeDeleted) {
+ private FHIRPersistenceContextImpl(FHIRPersistenceEvent pe, boolean includeDeleted) {
this.persistenceEvent = pe;
setIncludeDeleted(includeDeleted);
}
@@ -37,21 +145,21 @@ public FHIRPersistenceContextImpl(FHIRPersistenceEvent pe, boolean includeDelete
* @param pe
* @param ifNoneMatch
*/
- public FHIRPersistenceContextImpl(FHIRPersistenceEvent pe, Integer ifNoneMatch) {
+ private FHIRPersistenceContextImpl(FHIRPersistenceEvent pe, Integer ifNoneMatch) {
this.persistenceEvent = pe;
setIfNoneMatch(ifNoneMatch);
}
- public FHIRPersistenceContextImpl(FHIRPersistenceEvent pe, FHIRHistoryContext hc) {
+ private FHIRPersistenceContextImpl(FHIRPersistenceEvent pe, FHIRHistoryContext hc) {
this.persistenceEvent = pe;
this.historyContext = hc;
}
- public FHIRPersistenceContextImpl(FHIRPersistenceEvent pe, FHIRSearchContext sc) {
+ private FHIRPersistenceContextImpl(FHIRPersistenceEvent pe, FHIRSearchContext sc) {
this.persistenceEvent = pe;
this.searchContext = sc;
}
- public FHIRPersistenceContextImpl(FHIRPersistenceEvent pe, boolean includeDeleted, FHIRSearchContext sc) {
+ private FHIRPersistenceContextImpl(FHIRPersistenceEvent pe, boolean includeDeleted, FHIRSearchContext sc) {
this.persistenceEvent = pe;
setIncludeDeleted(includeDeleted);
this.searchContext = sc;
@@ -97,4 +205,16 @@ public void setIfNoneMatch(Integer ifNoneMatch) {
public Integer getIfNoneMatch() {
return this.ifNoneMatch;
}
+
+ @Override
+ public PayloadPersistenceResponse getOffloadResponse() {
+ return this.offloadResponse;
+ }
+
+ /**
+ * @param offloadResponse the offloadResponse to set
+ */
+ public void setOffloadResponse(PayloadPersistenceResponse offloadResponse) {
+ this.offloadResponse = offloadResponse;
+ }
}
\ No newline at end of file
diff --git a/fhir-persistence/src/main/java/com/ibm/fhir/persistence/payload/FHIRPayloadPartitionStrategy.java b/fhir-persistence/src/main/java/com/ibm/fhir/persistence/payload/FHIRPayloadPartitionStrategy.java
index d69ff18ca78..8402da8c06d 100644
--- a/fhir-persistence/src/main/java/com/ibm/fhir/persistence/payload/FHIRPayloadPartitionStrategy.java
+++ b/fhir-persistence/src/main/java/com/ibm/fhir/persistence/payload/FHIRPayloadPartitionStrategy.java
@@ -16,5 +16,5 @@ public interface FHIRPayloadPartitionStrategy {
* Ask for the partition name from this strategy
* @return
*/
- String getPartitionName();
+ String getPartitionName(String resourceType, String logicalId);
}
\ No newline at end of file
diff --git a/fhir-persistence/src/main/java/com/ibm/fhir/persistence/payload/FHIRPayloadPersistence.java b/fhir-persistence/src/main/java/com/ibm/fhir/persistence/payload/FHIRPayloadPersistence.java
index dc690ec8f97..b0b6d69763a 100644
--- a/fhir-persistence/src/main/java/com/ibm/fhir/persistence/payload/FHIRPayloadPersistence.java
+++ b/fhir-persistence/src/main/java/com/ibm/fhir/persistence/payload/FHIRPayloadPersistence.java
@@ -7,7 +7,6 @@
package com.ibm.fhir.persistence.payload;
import java.util.List;
-import java.util.concurrent.Future;
import com.ibm.fhir.model.resource.Resource;
import com.ibm.fhir.persistence.exception.FHIRPersistenceException;
@@ -25,40 +24,35 @@ public interface FHIRPayloadPersistence {
* @param resourceTypeId the database id assigned to this resource type
* @param logicalId the logical id of the resource
* @param version the version of the resource
+ * @param resourcePayloadKey the unique key used to tie this to the RDBMS record
* @param resource the resource to store
- * @return a {@link Future} holding the payload key and status.
+ * @return the payload key details and future result status.
*/
- Future storePayload(String resourceTypeName, int resourceTypeId, String logicalId, int version, Resource resource) throws FHIRPersistenceException;
+ PayloadPersistenceResponse storePayload(String resourceTypeName, int resourceTypeId, String logicalId, int version, String resourcePayloadKey, Resource resource) throws FHIRPersistenceException;
/**
* Retrieve the payload data for the given resourceTypeId, logicalId and version. Synchronous.
* @param resourceType the expected resource type class
- * @param resourceTypeId the unique int idenfifier for the resource type
+ * @param rowResourceTypeName the resource type name of the resource read from the database (matching the resourceTypeId)
+ * @param resourceTypeId the unique int identifier for the resource type name
* @param logicalId the logical identifier of the desired resource
* @param version the specific version of the desired resource
+ * @param resourcePayloadKey the resource payload key connecting the entry to the RDBMS record
* @param elements to filter elements within the resource - can be null
- * @return the fhirResourcePayload exactly as it was provided to {@link #storePayload(String, int, String, int, byte[])}
+ * @return the fhirResourcePayload exactly as it was provided to {@link #storePayload(String, int, String, int, String, byte[])}
*/
- T readResource(Class resourceType, int resourceTypeId, String logicalId, int version, List elements) throws FHIRPersistenceException;
+ T readResource(Class resourceType, String rowResourceTypeName, int resourceTypeId, String logicalId, int version, String resourcePayloadKey, List elements) throws FHIRPersistenceException;
/**
- * Fetch the resource directly using the payload key. This is faster than {@link #readResource(Class, int, String, int, List)}
- * because the payload persistence implementation can use the {@link PayloadKey} to directly address the location where the
- * payload is stored. Allows async implementations.
- * @param
+ * Delete the payload item. This may be called to clean up after a failed transaction or
+ * by the reconciliation process when it finds an orphaned record.
+ * when performing a hard delete on a resource.
* @param resourceType
- * @param payloadKey
- * @return a Future that will hold the resource after it has been read
- * @throws FHIRPersistenceException
- */
- Future readResource(Class resourceType, PayloadKey payloadKey) throws FHIRPersistenceException;
-
- /**
- * Delete the payload item. This may be called to clean up after a failed transaction
* @param resourceTypeId
* @param logicalId
- * @param version
+ * @param version the version id, or null for all versions
+ * @param resourcePayloadKey the key to make sure the entry matches the RDBMS record
* @throws FHIRPersistenceException
*/
- void deletePayload(int resourceTypeId, String logicalId, int version) throws FHIRPersistenceException;
+ void deletePayload(String resourceType, int resourceTypeId, String logicalId, Integer version, String resourcePayloadKey) throws FHIRPersistenceException;
}
\ No newline at end of file
diff --git a/fhir-persistence/src/main/java/com/ibm/fhir/persistence/payload/PayloadKey.java b/fhir-persistence/src/main/java/com/ibm/fhir/persistence/payload/PayloadPersistenceResponse.java
similarity index 55%
rename from fhir-persistence/src/main/java/com/ibm/fhir/persistence/payload/PayloadKey.java
rename to fhir-persistence/src/main/java/com/ibm/fhir/persistence/payload/PayloadPersistenceResponse.java
index 2fa6ec59c53..e969b0dbcbd 100644
--- a/fhir-persistence/src/main/java/com/ibm/fhir/persistence/payload/PayloadKey.java
+++ b/fhir-persistence/src/main/java/com/ibm/fhir/persistence/payload/PayloadPersistenceResponse.java
@@ -1,16 +1,22 @@
/*
- * (C) Copyright IBM Corp. 2021
+ * (C) Copyright IBM Corp. 2021, 2022
*
* SPDX-License-Identifier: Apache-2.0
*/
package com.ibm.fhir.persistence.payload;
+import java.util.concurrent.Future;
+
/**
- * A key used to identify a payload object stored by the payload persistence layer
+ * Data carrier encapsulating the response from the payload persistence component
+ * when making a call to offload the resource payload.
*/
-public class PayloadKey {
+public class PayloadPersistenceResponse {
+ // The UUID value used to tie together the RDBMS and offload records
+ private final String resourcePayloadKey;
+
// The string name of the resource type
private final String resourceTypeName;
@@ -23,56 +29,40 @@ public class PayloadKey {
// The version id of the resource
private final int versionId;
- // Identifies the partition used to store the payload in a partitioned system (like Cassandra)
- private final String partitionKey;
-
- // The identifier assigned by the payload persistence layer
- private final String payloadId;
-
- // The status of the payload persistence operation
- private final Status status;
+ // The (future) result status of the async persistence call
+ private final Future result;
- /**
- * Enumeration of status types
- */
- public static enum Status {
- OK, FAILED
- }
-
/**
* Public constructor
+ * @param resourcePayloadKey
* @param resourceTypeName
* @param resourceTypeId
* @param logicalId
* @param versionId
- * @param partitionKey
- * @param payloadId
- * @param status
+ * @param result
*/
- public PayloadKey(String resourceTypeName, int resourceTypeId, String logicalId, int versionId, String partitionKey, String payloadId,
- Status status) {
+ public PayloadPersistenceResponse(String resourcePayloadKey, String resourceTypeName, int resourceTypeId, String logicalId, int versionId,
+ Future result) {
+ this.resourcePayloadKey = resourcePayloadKey;
this.resourceTypeName = resourceTypeName;
this.resourceTypeId = resourceTypeId;
this.logicalId = logicalId;
this.versionId = versionId;
- this.partitionKey = partitionKey;
- this.payloadId = payloadId;
- this.status = status;
+ this.result = result;
}
@Override
public String toString() {
StringBuilder result = new StringBuilder();
- result.append(partitionKey);
- result.append("-");
- result.append(payloadId);
- result.append("[");
result.append(resourceTypeName);
- result.append("/");
+ result.append("[");
+ result.append(resourceTypeId);
+ result.append("]/");
result.append(logicalId);
result.append("/");
result.append(versionId);
- result.append("]");
+ result.append("/");
+ result.append(this.resourcePayloadKey);
return result.toString();
}
@@ -105,23 +95,16 @@ public int getVersionId() {
}
/**
- * @return the partitionKey
- */
- public String getPartitionKey() {
- return partitionKey;
- }
-
- /**
- * @return the payloadId
+ * @return the resourcePayloadKey
*/
- public String getPayloadId() {
- return payloadId;
+ public String getResourcePayloadKey() {
+ return resourcePayloadKey;
}
/**
- * @return the status
+ * @return the result
*/
- public Status getStatus() {
- return status;
+ public Future getResult() {
+ return result;
}
}
\ No newline at end of file
diff --git a/fhir-persistence/src/main/java/com/ibm/fhir/persistence/payload/PayloadPersistenceResult.java b/fhir-persistence/src/main/java/com/ibm/fhir/persistence/payload/PayloadPersistenceResult.java
new file mode 100644
index 00000000000..013ff4a3a2e
--- /dev/null
+++ b/fhir-persistence/src/main/java/com/ibm/fhir/persistence/payload/PayloadPersistenceResult.java
@@ -0,0 +1,33 @@
+/*
+ * (C) Copyright IBM Corp. 2021
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+package com.ibm.fhir.persistence.payload;
+
+/**
+ * The response from the payload persistence operation
+ */
+public class PayloadPersistenceResult {
+ // The status of the payload persistence operation
+ private final Status status;
+
+ /**
+ * Enumeration of status types
+ */
+ public static enum Status {
+ OK, FAILED
+ }
+
+ public PayloadPersistenceResult(Status status) {
+ this.status = status;
+ }
+
+ /**
+ * @return the status
+ */
+ public Status getStatus() {
+ return status;
+ }
+}
\ No newline at end of file
diff --git a/fhir-persistence/src/main/java/com/ibm/fhir/persistence/payload/PayloadReader.java b/fhir-persistence/src/main/java/com/ibm/fhir/persistence/payload/PayloadReader.java
new file mode 100644
index 00000000000..fa748d23661
--- /dev/null
+++ b/fhir-persistence/src/main/java/com/ibm/fhir/persistence/payload/PayloadReader.java
@@ -0,0 +1,28 @@
+/*
+ * (C) Copyright IBM Corp. 2021
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+package com.ibm.fhir.persistence.payload;
+
+import java.io.InputStream;
+
+import com.ibm.fhir.model.resource.Resource;
+import com.ibm.fhir.persistence.exception.FHIRPersistenceException;
+
+/**
+ * Strategy for reading a resource from a stream
+ */
+public interface PayloadReader {
+
+ /**
+ * Read the resource of type T from the {@link InputStream}.
+ * @param
+ * @param resourceType
+ * @param is
+ * @return
+ * @throws FHIRPersistenceException
+ */
+ T read(Class resourceType, InputStream is) throws FHIRPersistenceException;
+}
diff --git a/fhir-persistence/src/main/java/com/ibm/fhir/persistence/payload/PayloadReaderImpl.java b/fhir-persistence/src/main/java/com/ibm/fhir/persistence/payload/PayloadReaderImpl.java
new file mode 100644
index 00000000000..77551a8288a
--- /dev/null
+++ b/fhir-persistence/src/main/java/com/ibm/fhir/persistence/payload/PayloadReaderImpl.java
@@ -0,0 +1,47 @@
+/*
+ * (C) Copyright IBM Corp. 2021
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+package com.ibm.fhir.persistence.payload;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.List;
+
+import com.ibm.fhir.model.parser.exception.FHIRParserException;
+import com.ibm.fhir.model.resource.Resource;
+import com.ibm.fhir.persistence.FHIRPersistenceSupport;
+import com.ibm.fhir.persistence.exception.FHIRPersistenceException;
+
+
+/**
+ * Strategy for reading a payload object with optional compression
+ */
+public class PayloadReaderImpl implements PayloadReader {
+ // Is the input stream compressed?
+ private final boolean uncompress;
+
+ // Subset elements when parsing the Resource
+ private final List elements;
+
+ /**
+ * Public constructor
+ * @param uncompress
+ * @param elements
+ */
+ public PayloadReaderImpl(boolean uncompress, List elements) {
+ this.uncompress = uncompress;
+ this.elements = elements;
+ }
+
+ @Override
+ public T read(Class resourceType, InputStream inputStream) throws FHIRPersistenceException {
+ try {
+ return FHIRPersistenceSupport.parse(resourceType, inputStream, elements, uncompress);
+ } catch (IOException | FHIRParserException x) {
+ throw new FHIRPersistenceException("Error reading resource", x);
+ }
+ }
+}
diff --git a/fhir-persistence/src/main/java/com/ibm/fhir/persistence/util/InputOutputByteStream.java b/fhir-persistence/src/main/java/com/ibm/fhir/persistence/util/InputOutputByteStream.java
index 4ac8ee44479..a510570c40d 100644
--- a/fhir-persistence/src/main/java/com/ibm/fhir/persistence/util/InputOutputByteStream.java
+++ b/fhir-persistence/src/main/java/com/ibm/fhir/persistence/util/InputOutputByteStream.java
@@ -73,7 +73,7 @@ private class ByteOutputStream extends OutputStream {
@Override
public void write(int b) throws IOException {
int idx = offset++;
- extend(idx);
+ extend(offset); // use the new length
buffer[idx] = (byte)b;
}
@@ -167,8 +167,12 @@ public InputOutputByteStream(int initialCapacity) {
this.reshapeStrat = new ReshapeStrategy();
}
+ /**
+ * Adopt a buffer which may already contain data
+ * @param adoptBuffer
+ * @param offset
+ */
public InputOutputByteStream(byte[] adoptBuffer, int offset) {
- // Adopt a buffer which may already contain data
this.buffer = adoptBuffer;
this.offset = offset;
@@ -178,6 +182,23 @@ public InputOutputByteStream(byte[] adoptBuffer, int offset) {
}
this.reshapeStrat = new ReshapeStrategy();
}
+
+ /**
+ * Initialize the internal buffer by copying the contents of the given ByteBuffer
+ * (which can be read-only).
+ * @param bb
+ */
+ public InputOutputByteStream(ByteBuffer bb) {
+ int size = bb.remaining();
+ if (size < 1) {
+ throw new IllegalArgumentException("Buffer is empty");
+ }
+
+ this.buffer = new byte[size];
+ bb.get(buffer);
+ this.offset = size;
+ this.reshapeStrat = new ReshapeStrategy();
+ }
/**
* Create a buffer with a given capacity and override the {@link ReshapeStrategy}
@@ -248,4 +269,12 @@ public ByteBuffer wrap() {
public void reset() {
this.offset = 0;
}
+
+ /**
+ * Get the underlying byte[] buffer at the current point in time.
+ * @return
+ */
+ public byte[] getRawBuffer() {
+ return this.buffer;
+ }
}
\ No newline at end of file
diff --git a/fhir-persistence/src/test/java/com/ibm/fhir/persistence/test/MockPersistenceImpl.java b/fhir-persistence/src/test/java/com/ibm/fhir/persistence/test/MockPersistenceImpl.java
index 698c4920270..b7ae6fbca63 100644
--- a/fhir-persistence/src/test/java/com/ibm/fhir/persistence/test/MockPersistenceImpl.java
+++ b/fhir-persistence/src/test/java/com/ibm/fhir/persistence/test/MockPersistenceImpl.java
@@ -9,7 +9,6 @@
import java.time.Instant;
import java.util.Collections;
import java.util.List;
-import java.util.concurrent.Future;
import java.util.function.Function;
import com.ibm.fhir.model.resource.OperationOutcome;
@@ -24,7 +23,7 @@
import com.ibm.fhir.persistence.context.FHIRPersistenceContext;
import com.ibm.fhir.persistence.exception.FHIRPersistenceException;
import com.ibm.fhir.persistence.exception.FHIRPersistenceResourceDeletedException;
-import com.ibm.fhir.persistence.payload.PayloadKey;
+import com.ibm.fhir.persistence.payload.PayloadPersistenceResponse;
/**
* Mock implementation of FHIRPersistence for use during testing.
@@ -128,7 +127,7 @@ public SingleResourceResult updateWithMeta(FHIRPersisten
}
@Override
- public Future storePayload(Resource resource, String logicalId, int newVersionNumber) {
+ public PayloadPersistenceResponse storePayload(Resource resource, String logicalId, int newVersionNumber, String resourcePayloadKey) {
return null;
}
diff --git a/fhir-persistence/src/test/java/com/ibm/fhir/persistence/test/common/AbstractPersistenceTest.java b/fhir-persistence/src/test/java/com/ibm/fhir/persistence/test/common/AbstractPersistenceTest.java
index e6736663463..ad64ff540ea 100644
--- a/fhir-persistence/src/test/java/com/ibm/fhir/persistence/test/common/AbstractPersistenceTest.java
+++ b/fhir-persistence/src/test/java/com/ibm/fhir/persistence/test/common/AbstractPersistenceTest.java
@@ -29,10 +29,7 @@
import com.ibm.fhir.config.FHIRConfiguration;
import com.ibm.fhir.config.FHIRRequestContext;
import com.ibm.fhir.model.resource.Resource;
-import com.ibm.fhir.model.resource.Resource.Builder;
-import com.ibm.fhir.model.type.Id;
import com.ibm.fhir.model.type.Instant;
-import com.ibm.fhir.model.type.Meta;
import com.ibm.fhir.persistence.FHIRPersistence;
import com.ibm.fhir.persistence.MultiResourceResult;
import com.ibm.fhir.persistence.context.FHIRHistoryContext;
diff --git a/fhir-persistence/src/test/java/com/ibm/fhir/persistence/test/common/AbstractReverseChainTest.java b/fhir-persistence/src/test/java/com/ibm/fhir/persistence/test/common/AbstractReverseChainTest.java
index be15e31eae0..207642adce2 100644
--- a/fhir-persistence/src/test/java/com/ibm/fhir/persistence/test/common/AbstractReverseChainTest.java
+++ b/fhir-persistence/src/test/java/com/ibm/fhir/persistence/test/common/AbstractReverseChainTest.java
@@ -86,6 +86,7 @@ public void createResources() throws Exception {
Coding uniqueTag = Coding.builder().system(uri("http://ibm.com/fhir/tag")).code(code(now.toString())).build();
Coding uniqueSecurity = Coding.builder().system(uri("http://ibm.com/fhir/security")).code(code(now.toString())).build();
+ startTrx();
// Organizations that will be referenced by a Patient
savedOrg1 = org.toBuilder().active(com.ibm.fhir.model.type.Boolean.of(true)).build();
savedOrg1 = persistence.create(getDefaultPersistenceContext(), savedOrg1).getResource();
@@ -180,6 +181,7 @@ public void createResources() throws Exception {
.device(reference("Device/" + savedDevice2.getId() + "/_history/2"))
.build();
savedObservation6 = persistence.create(getDefaultPersistenceContext(), savedObservation6).getResource();
+ commitTrx();
}
@AfterClass
diff --git a/fhir-server-spi/src/main/java/com/ibm/fhir/server/spi/operation/FHIRResourceHelpers.java b/fhir-server-spi/src/main/java/com/ibm/fhir/server/spi/operation/FHIRResourceHelpers.java
index d0930140a9e..b21673350fd 100644
--- a/fhir-server-spi/src/main/java/com/ibm/fhir/server/spi/operation/FHIRResourceHelpers.java
+++ b/fhir-server-spi/src/main/java/com/ibm/fhir/server/spi/operation/FHIRResourceHelpers.java
@@ -9,7 +9,6 @@
import java.time.Instant;
import java.util.List;
import java.util.Map;
-import java.util.concurrent.Future;
import javax.ws.rs.core.MultivaluedMap;
@@ -25,7 +24,7 @@
import com.ibm.fhir.persistence.context.FHIRPersistenceEvent;
import com.ibm.fhir.persistence.erase.EraseDTO;
import com.ibm.fhir.persistence.exception.FHIRPersistenceException;
-import com.ibm.fhir.persistence.payload.PayloadKey;
+import com.ibm.fhir.persistence.payload.PayloadPersistenceResponse;
import com.ibm.fhir.search.context.FHIRSearchContext;
/**
@@ -134,10 +133,11 @@ FHIRRestOperationResponse doCreateMeta(FHIRPersistenceEvent event, List w
* @param event
* @param warnings
* @param resource
+ * @param offloadResponse
* @return
* @throws Exception
*/
- FHIRRestOperationResponse doCreatePersist(FHIRPersistenceEvent event, List warnings, Resource resource) throws Exception;
+ FHIRRestOperationResponse doCreatePersist(FHIRPersistenceEvent event, List warnings, Resource resource, PayloadPersistenceResponse offloadResponse) throws Exception;
/**
* 1st phase of update interaction.
@@ -168,11 +168,12 @@ FHIRRestOperationResponse doUpdateMeta(FHIRPersistenceEvent event, String type,
* @param warnings
* @param isDeleted
* @param ifNoneMatch
+ * @param offloadResponse
* @return
* @throws Exception
*/
public FHIRRestOperationResponse doPatchOrUpdatePersist(FHIRPersistenceEvent event, String type, String id, boolean isPatch,
- Resource newResource, Resource prevResource, List warnings, boolean isDeleted, Integer ifNoneMatch) throws Exception;
+ Resource newResource, Resource prevResource, List warnings, boolean isDeleted, Integer ifNoneMatch, PayloadPersistenceResponse offloadResponse) throws Exception;
/**
* Builds a collection of properties that will be passed to the persistence interceptors.
@@ -540,9 +541,10 @@ default ResourceEraseRecord doErase(FHIROperationContext operationContext, Erase
* @param resource the resource to store (with correct Meta fields)
* @param logicalId the logical id of the resource
* @param newVersionNumber the version number to use
- * @return a Future response to the payload store operation, or null if it is not supported
+ * @param resourcePayloadKey the key used to tie the RDBMS record with the offload record
+ * @return a response to the payload store operation, or null if it is not supported
*/
- Future storePayload(Resource resource, String logicalId, int newVersionNumber) throws Exception;
+ PayloadPersistenceResponse storePayload(Resource resource, String logicalId, int newVersionNumber, String resourcePayloadKey) throws Exception;
/**
* Validate a resource. First validate profile assertions for the resource if configured to do so,
diff --git a/fhir-server-spi/src/main/java/com/ibm/fhir/server/spi/operation/FHIRRestOperationResponse.java b/fhir-server-spi/src/main/java/com/ibm/fhir/server/spi/operation/FHIRRestOperationResponse.java
index 225627d5323..e6342c0d175 100644
--- a/fhir-server-spi/src/main/java/com/ibm/fhir/server/spi/operation/FHIRRestOperationResponse.java
+++ b/fhir-server-spi/src/main/java/com/ibm/fhir/server/spi/operation/FHIRRestOperationResponse.java
@@ -7,13 +7,12 @@
package com.ibm.fhir.server.spi.operation;
import java.net.URI;
-import java.util.concurrent.Future;
import javax.ws.rs.core.Response;
import com.ibm.fhir.model.resource.OperationOutcome;
import com.ibm.fhir.model.resource.Resource;
-import com.ibm.fhir.persistence.payload.PayloadKey;
+import com.ibm.fhir.persistence.payload.PayloadPersistenceResponse;
/**
* This class is used to represent a response returned by the FHIR resource helper methods.
@@ -30,7 +29,7 @@ public class FHIRRestOperationResponse {
private boolean completed;
// A nested response we may get when offloading payload storage (e.g. in COS, Cassandra)
- private Future storePayloadResponse;
+ private PayloadPersistenceResponse storePayloadResponse;
// The id of the resource, which could be new in the case of create
private String resourceId;
@@ -49,7 +48,7 @@ public FHIRRestOperationResponse(Response.Status status, URI locationURI, Operat
setOperationOutcome(operationOutcome);
}
- public FHIRRestOperationResponse(Resource resource, String resourceId, Future storePayloadResponse) {
+ public FHIRRestOperationResponse(Resource resource, String resourceId, PayloadPersistenceResponse storePayloadResponse) {
this.resource = resource;
this.resourceId = resourceId;
this.setStorePayloadResponse(storePayloadResponse);
@@ -129,14 +128,14 @@ public void setCompleted(boolean completed) {
/**
* @return the storePayloadResponse
*/
- public Future getStorePayloadResponse() {
+ public PayloadPersistenceResponse getStorePayloadResponse() {
return storePayloadResponse;
}
/**
* @param storePayloadResponse the storePayloadResponse to set
*/
- public void setStorePayloadResponse(Future storePayloadResponse) {
+ public void setStorePayloadResponse(PayloadPersistenceResponse storePayloadResponse) {
this.storePayloadResponse = storePayloadResponse;
}
-}
+}
\ No newline at end of file
diff --git a/fhir-server-test/src/test/java/com/ibm/fhir/server/test/examples/R4ExampleServerTest.java b/fhir-server-test/src/test/java/com/ibm/fhir/server/test/examples/R4ExampleServerTest.java
index cb3e0a53e6b..da91fdaf984 100644
--- a/fhir-server-test/src/test/java/com/ibm/fhir/server/test/examples/R4ExampleServerTest.java
+++ b/fhir-server-test/src/test/java/com/ibm/fhir/server/test/examples/R4ExampleServerTest.java
@@ -6,11 +6,13 @@
package com.ibm.fhir.server.test.examples;
+import java.util.Properties;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import org.testng.annotations.Test;
+import com.ibm.fhir.client.FHIRClient;
import com.ibm.fhir.examples.Index;
import com.ibm.fhir.model.spec.test.DriverMetrics;
import com.ibm.fhir.model.spec.test.R4ExamplesDriver;
@@ -21,6 +23,9 @@
* Basic sniff test of the FHIR Server.
*/
public class R4ExampleServerTest extends FHIRServerTestBase {
+
+ // the tenant id to use for the FHIR server requests
+ private String tenantId;
/**
* Process all the examples in the fhir-r4-spec example library
@@ -34,14 +39,21 @@ public void processExamples() throws Exception {
// Setup a Pool
ExecutorService es = Executors.newFixedThreadPool(5);
driver.setPool(es, 5);
+
DriverMetrics dm = new DriverMetrics();
driver.setMetrics(dm);
driver.setValidator(new ValidationProcessor());
- driver.setProcessor(new ExampleRequestProcessor(this, "default", dm, 1));
+ driver.setProcessor(new ExampleRequestProcessor(this, tenantId, dm, 1));
String index = System.getProperty(this.getClass().getName()
+ ".index", Index.MINIMAL_JSON.name());
driver.processIndex(Index.valueOf(index));
}
+
+ @Override
+ public void setUp(Properties properties) throws Exception {
+ super.setUp(properties);
+ this.tenantId = properties.getProperty(FHIRClient.PROPNAME_TENANT_ID, "default");
+ }
}
diff --git a/fhir-server-test/src/test/java/com/ibm/fhir/server/test/operation/EraseOperationTest.java b/fhir-server-test/src/test/java/com/ibm/fhir/server/test/operation/EraseOperationTest.java
index 67f9428cb83..40a49f29d20 100644
--- a/fhir-server-test/src/test/java/com/ibm/fhir/server/test/operation/EraseOperationTest.java
+++ b/fhir-server-test/src/test/java/com/ibm/fhir/server/test/operation/EraseOperationTest.java
@@ -225,16 +225,17 @@ private void eraseResource(String resourceType, String logicalId, boolean error,
private void eraseResourceByVersion(String resourceType, String logicalId, Integer version, boolean error, String msg, boolean patient, boolean reason, String reasonMsg) {
Entity entity = Entity.entity(generateParameters(patient, reason, reasonMsg, Optional.of(version)), FHIRMediaType.APPLICATION_FHIR_JSON);
+ final String requestPath = "/" + resourceType + "/" + logicalId + "/$erase";
Response r = getWebTarget()
- .path("/" + resourceType + "/" + logicalId + "/$erase")
+ .path(requestPath)
.request(FHIRMediaType.APPLICATION_FHIR_JSON)
.header("X-FHIR-TENANT-ID", "default")
.header("X-FHIR-DSID", "default")
.post(entity, Response.class);
if (error) {
- assertEquals(r.getStatus(), Response.Status.BAD_REQUEST.getStatusCode());
+ assertEquals(r.getStatus(), Response.Status.BAD_REQUEST.getStatusCode(), requestPath);
} else {
- assertEquals(r.getStatus(), Response.Status.OK.getStatusCode());
+ assertEquals(r.getStatus(), Response.Status.OK.getStatusCode(), requestPath);
}
}
@@ -409,12 +410,13 @@ private void checkResourceDeletedNotErased(String resourceType, String logicalId
*/
private void checkResourceHistoryDoesNotExist(String resourceType, String logicalId, Integer version) {
WebTarget target = getWebTarget();
- target = target.path("/" + resourceType + "/" + logicalId + "/_history/" + version);
+ final String resourcePath = "/" + resourceType + "/" + logicalId + "/_history/" + version;
+ target = target.path(resourcePath);
Response r = target.request(FHIRMediaType.APPLICATION_FHIR_JSON)
.header("X-FHIR-TENANT-ID", "default")
.header("X-FHIR-DSID", "default")
.get(Response.class);
- assertEquals(r.getStatus(), Status.NOT_FOUND.getStatusCode());
+ assertEquals(r.getStatus(), Status.NOT_FOUND.getStatusCode(), resourcePath);
}
/**
diff --git a/fhir-server-test/src/test/resources/test.properties b/fhir-server-test/src/test/resources/test.properties
index 057ec37a767..629b05a65ee 100644
--- a/fhir-server-test/src/test/resources/test.properties
+++ b/fhir-server-test/src/test/resources/test.properties
@@ -36,7 +36,9 @@ test.kafka.topicName = fhirNotifications
fhirclient.logging.enabled = false
fhirclient.hostnameVerification.enabled = false
-fhirclient.http.receive.timeout = 60000
+
+# Longer than the default Liberty transaction timeout 120s
+fhirclient.http.receive.timeout = 130000
fhirclient.http.return.pref = minimal
# Used to turn on or off tests or throttle
diff --git a/fhir-server/src/main/java/com/ibm/fhir/server/rest/FHIRRestInteractionCreate.java b/fhir-server/src/main/java/com/ibm/fhir/server/rest/FHIRRestInteractionCreate.java
index ffc5ce101c1..a5b67be4282 100644
--- a/fhir-server/src/main/java/com/ibm/fhir/server/rest/FHIRRestInteractionCreate.java
+++ b/fhir-server/src/main/java/com/ibm/fhir/server/rest/FHIRRestInteractionCreate.java
@@ -45,12 +45,18 @@ public FHIRRestInteractionCreate(int entryIndex, FHIRPersistenceEvent event, Ent
@Override
public void process(FHIRRestInteractionVisitor visitor) throws Exception {
FHIRRestOperationResponse result = visitor.doCreate(getEntryIndex(), getEvent(), getWarnings(),
- getValidationResponseEntry(), getRequestDescription(), getRequestURL(),
- getAccumulatedTime(), type, getNewResource(), ifNoneExist, localIdentifier);
+ getValidationResponseEntry(), getRequestDescription(), getRequestURL(), getAccumulatedTime(), type,
+ getNewResource(), ifNoneExist, localIdentifier, getOffloadResponse());
// update the resource so we can use it when called in the next processing phase
- if (result != null && result.getResource() != null) {
- setNewResource(result.getResource());
+ if (result != null) {
+ if (result.getResource() != null) {
+ setNewResource(result.getResource());
+ }
+
+ if (result.getStorePayloadResponse() != null) {
+ setOffloadResponse(result.getStorePayloadResponse());
+ }
}
}
}
\ No newline at end of file
diff --git a/fhir-server/src/main/java/com/ibm/fhir/server/rest/FHIRRestInteractionPatch.java b/fhir-server/src/main/java/com/ibm/fhir/server/rest/FHIRRestInteractionPatch.java
index 317c7bab7f3..f024f309b10 100644
--- a/fhir-server/src/main/java/com/ibm/fhir/server/rest/FHIRRestInteractionPatch.java
+++ b/fhir-server/src/main/java/com/ibm/fhir/server/rest/FHIRRestInteractionPatch.java
@@ -57,7 +57,7 @@ public FHIRRestInteractionPatch(int entryIndex, FHIRPersistenceEvent event, Stri
public void process(FHIRRestInteractionVisitor visitor) throws Exception {
FHIRRestOperationResponse result = visitor.doPatch(getEntryIndex(), getEvent(), getValidationResponseEntry(),
getRequestDescription(), getRequestURL(), getAccumulatedTime(), type, id, getNewResource(),
- getPrevResource(), patch, ifMatchValue, searchQueryString, skippableUpdate, getWarnings(), localIdentifier);
+ getPrevResource(), patch, ifMatchValue, searchQueryString, skippableUpdate, getWarnings(), localIdentifier, getOffloadResponse());
// If the response includes a resource, update our copy so that we can pass to the
// next visitor.
@@ -69,6 +69,10 @@ public void process(FHIRRestInteractionVisitor visitor) throws Exception {
if (result.getPrevResource() != null) {
setPrevResource(result.getPrevResource());
}
+
+ if (result.getStorePayloadResponse() != null) {
+ setOffloadResponse(result.getStorePayloadResponse());
+ }
}
}
}
\ No newline at end of file
diff --git a/fhir-server/src/main/java/com/ibm/fhir/server/rest/FHIRRestInteractionResource.java b/fhir-server/src/main/java/com/ibm/fhir/server/rest/FHIRRestInteractionResource.java
index f290798bc21..e406d33934a 100644
--- a/fhir-server/src/main/java/com/ibm/fhir/server/rest/FHIRRestInteractionResource.java
+++ b/fhir-server/src/main/java/com/ibm/fhir/server/rest/FHIRRestInteractionResource.java
@@ -9,6 +9,7 @@
import com.ibm.fhir.model.resource.Bundle.Entry;
import com.ibm.fhir.model.resource.Resource;
import com.ibm.fhir.persistence.context.FHIRPersistenceEvent;
+import com.ibm.fhir.persistence.payload.PayloadPersistenceResponse;
import com.ibm.fhir.server.util.FHIRUrlParser;
/**
@@ -26,6 +27,9 @@ public abstract class FHIRRestInteractionResource extends FHIRRestInteractionBas
// The previous resource (e.g. if read from the database
private Resource prevResource;
+
+ // The response from payload persistence when offloading
+ private PayloadPersistenceResponse offloadResponse;
/**
* Protected constructor
@@ -90,4 +94,18 @@ public Resource getPrevResource() {
public FHIRPersistenceEvent getEvent() {
return event;
}
+
+ /**
+ * @return the offloadResponse
+ */
+ public PayloadPersistenceResponse getOffloadResponse() {
+ return offloadResponse;
+ }
+
+ /**
+ * @param offloadResponse the offloadResponse to set
+ */
+ public void setOffloadResponse(PayloadPersistenceResponse offloadResponse) {
+ this.offloadResponse = offloadResponse;
+ }
}
\ No newline at end of file
diff --git a/fhir-server/src/main/java/com/ibm/fhir/server/rest/FHIRRestInteractionUpdate.java b/fhir-server/src/main/java/com/ibm/fhir/server/rest/FHIRRestInteractionUpdate.java
index 52fe8531a52..98e3cd5d337 100644
--- a/fhir-server/src/main/java/com/ibm/fhir/server/rest/FHIRRestInteractionUpdate.java
+++ b/fhir-server/src/main/java/com/ibm/fhir/server/rest/FHIRRestInteractionUpdate.java
@@ -64,7 +64,8 @@ public void process(FHIRRestInteractionVisitor visitor) throws Exception {
FHIRRestOperationResponse result = visitor.doUpdate(getEntryIndex(), getEvent(), getValidationResponseEntry(),
getRequestDescription(), getRequestURL(), getAccumulatedTime(), type, id, getNewResource(),
- getPrevResource(), ifMatchValue, searchQueryString, skippableUpdate, localIdentifier, getWarnings(), deleted, ifNoneMatch);
+ getPrevResource(), ifMatchValue, searchQueryString, skippableUpdate, localIdentifier, getWarnings(), deleted, ifNoneMatch,
+ getOffloadResponse());
// update the resource so we can use it when called in the next processing phase
if (result != null) {
@@ -75,7 +76,11 @@ public void process(FHIRRestInteractionVisitor visitor) throws Exception {
if (result.getPrevResource() != null) {
setPrevResource(result.getPrevResource());
}
-
+
+ if (result.getStorePayloadResponse() != null) {
+ setOffloadResponse(result.getStorePayloadResponse());
+ }
+
// Record the deletion status so we can return the correct response when undeleting
this.deleted = result.isDeleted();
}
diff --git a/fhir-server/src/main/java/com/ibm/fhir/server/rest/FHIRRestInteractionVisitor.java b/fhir-server/src/main/java/com/ibm/fhir/server/rest/FHIRRestInteractionVisitor.java
index e01a885d789..67c8af05613 100644
--- a/fhir-server/src/main/java/com/ibm/fhir/server/rest/FHIRRestInteractionVisitor.java
+++ b/fhir-server/src/main/java/com/ibm/fhir/server/rest/FHIRRestInteractionVisitor.java
@@ -16,6 +16,7 @@
import com.ibm.fhir.model.resource.OperationOutcome.Issue;
import com.ibm.fhir.model.resource.Resource;
import com.ibm.fhir.persistence.context.FHIRPersistenceEvent;
+import com.ibm.fhir.persistence.payload.PayloadPersistenceResponse;
import com.ibm.fhir.server.spi.operation.FHIROperationContext;
import com.ibm.fhir.server.spi.operation.FHIRRestOperationResponse;
import com.ibm.fhir.server.util.FHIRUrlParser;
@@ -141,12 +142,14 @@ FHIRRestOperationResponse doHistory(int entryIndex, String requestDescription, F
* @param ifNoneExist
* whether to create the resource if none exists
* @param localIdentifier
+ * @param offloadResponse
+ * the response from payload persistence when offloading
* @return a FHIRRestOperationResponse object containing the results of the operation
* @throws Exception
*/
FHIRRestOperationResponse doCreate(int entryIndex, FHIRPersistenceEvent event, List warnings,
Entry validationResponseEntry, String requestDescription, FHIRUrlParser requestURL, long accumulatedTime,
- String type, Resource resource, String ifNoneExist, String localIdentifier) throws Exception;
+ String type, Resource resource, String ifNoneExist, String localIdentifier, PayloadPersistenceResponse offloadResponse) throws Exception;
/**
* Performs an update operation (a new version of the Resource will be stored).
@@ -180,13 +183,16 @@ FHIRRestOperationResponse doCreate(int entryIndex, FHIRPersistenceEvent event, L
* flag to indicate if the resource is currently deleted
* @param ifNoneMatch
* conditional create-on-update
+ * @param offloadResponse
+ * the response from payload persistence when offloading
* @return a FHIRRestOperationResponse that contains the results of the operation
* @throws Exception
*/
FHIRRestOperationResponse doUpdate(int entryIndex, FHIRPersistenceEvent event, Entry validationResponseEntry,
String requestDescription, FHIRUrlParser requestURL, long accumulatedTime, String type, String id,
Resource newResource, Resource prevResource, String ifMatchValue, String searchQueryString,
- boolean skippableUpdate, String localIdentifier, List warnings, boolean isDeleted, Integer ifNoneMatch) throws Exception;
+ boolean skippableUpdate, String localIdentifier, List warnings, boolean isDeleted, Integer ifNoneMatch,
+ PayloadPersistenceResponse offloadResponse) throws Exception;
/**
* Performs a patch operation (a new version of the Resource will be stored).
@@ -215,6 +221,8 @@ FHIRRestOperationResponse doUpdate(int entryIndex, FHIRPersistenceEvent event, E
* @param skippableUpdate
* if true, and the result of the patch matches the existing resource on the server, then skip the update;
* if false, then always attempt the update
+ * @param offloadResponse
+ * response from payload persistencen when offloading
* @param warnings
* @param localIdentifier
* @return a FHIRRestOperationResponse that contains the results of the operation
@@ -223,7 +231,7 @@ FHIRRestOperationResponse doUpdate(int entryIndex, FHIRPersistenceEvent event, E
FHIRRestOperationResponse doPatch(int entryIndex, FHIRPersistenceEvent event, Entry validationResponseEntry,
String requestDescription, FHIRUrlParser requestURL, long accumulatedTime, String type, String id,
Resource newResource, Resource prevResource, FHIRPatch patch, String ifMatchValue, String searchQueryString,
- boolean skippableUpdate, List warnings, String localIdentifier) throws Exception;
+ boolean skippableUpdate, List warnings, String localIdentifier, PayloadPersistenceResponse offloadResponse) throws Exception;
/**
* Helper method which invokes a custom operation.
diff --git a/fhir-server/src/main/java/com/ibm/fhir/server/rest/FHIRRestInteractionVisitorMeta.java b/fhir-server/src/main/java/com/ibm/fhir/server/rest/FHIRRestInteractionVisitorMeta.java
index b88fc2f40bc..89221fa6383 100644
--- a/fhir-server/src/main/java/com/ibm/fhir/server/rest/FHIRRestInteractionVisitorMeta.java
+++ b/fhir-server/src/main/java/com/ibm/fhir/server/rest/FHIRRestInteractionVisitorMeta.java
@@ -41,6 +41,7 @@
import com.ibm.fhir.persistence.context.FHIRPersistenceEvent;
import com.ibm.fhir.persistence.exception.FHIRPersistenceResourceDeletedException;
import com.ibm.fhir.persistence.exception.FHIRPersistenceResourceNotFoundException;
+import com.ibm.fhir.persistence.payload.PayloadPersistenceResponse;
import com.ibm.fhir.search.SearchConstants;
import com.ibm.fhir.search.exception.FHIRSearchException;
import com.ibm.fhir.server.exception.FHIRRestBundledRequestException;
@@ -110,7 +111,7 @@ public FHIRRestOperationResponse doHistory(int entryIndex, String requestDescrip
@Override
public FHIRRestOperationResponse doCreate(int entryIndex, FHIRPersistenceEvent event, List warnings,
Entry validationResponseEntry, String requestDescription, FHIRUrlParser requestURL, long accumulatedTime,
- String type, Resource resource, String ifNoneExist, String localIdentifier) throws Exception {
+ String type, Resource resource, String ifNoneExist, String localIdentifier, PayloadPersistenceResponse offloadResponse) throws Exception {
logStart(entryIndex, requestDescription, requestURL);
// Skip CREATE if validation failed
@@ -161,7 +162,7 @@ public FHIRRestOperationResponse doCreate(int entryIndex, FHIRPersistenceEvent e
public FHIRRestOperationResponse doUpdate(int entryIndex, FHIRPersistenceEvent event, Entry validationResponseEntry,
String requestDescription, FHIRUrlParser requestURL, long accumulatedTime, String type, String id,
Resource resource, Resource prevResource, String ifMatchValue, String searchQueryString, boolean skippableUpdate,
- String localIdentifier, List warnings, boolean isDeleted, Integer ifNoneMatch) throws Exception {
+ String localIdentifier, List warnings, boolean isDeleted, Integer ifNoneMatch, PayloadPersistenceResponse offloadResponse) throws Exception {
logStart(entryIndex, requestDescription, requestURL);
// Skip UPDATE if validation failed
@@ -202,7 +203,7 @@ public FHIRRestOperationResponse doUpdate(int entryIndex, FHIRPersistenceEvent e
public FHIRRestOperationResponse doPatch(int entryIndex, FHIRPersistenceEvent event, Entry validationResponseEntry,
String requestDescription, FHIRUrlParser requestURL, long accumulatedTime, String type, String id, Resource newResource,
Resource prevResource, FHIRPatch patch, String ifMatchValue, String searchQueryString,
- boolean skippableUpdate, List