This page describes how to use point-in-time recovery (PITR) to recover FHIR resources in a FHIR store to a state within the last 21 days. You can use PITR to recover from unwanted changes, such as accidentally deleting FHIR resources.
Before you begin
PITR requests are categorized as advanced operation requests and are billed accordingly. Before using PITR, review the pricing for advanced-operation requests.
PITR and FHIR resource version history
PITR doesn't depend on FHIR resource version history.
You can still use PITR if the disableResourceVersioning
field in a FHIR store is true
, or if a FHIR resource's historical
versions have been purged.
Recovery workflow
To ensure a production recovery runs as expected, first do a dry run. The dry run outputs one or more files containing the IDs and types of the FHIR resources to recover. Verify the correctness of the output files before running the recovery again in production.
To recover specific resources, or recover resources according to a filtering criteria, specify a filter.
Do a dry run
Before recovering FHIR resources in production, do a dry run.
The following samples show how to do a dry run
using the fhirStores.rollback
method.
REST
Recover the FHIR resources.
To do a dry run, ensure the
force
field isfalse
.Before using any of the request data, make the following replacements:
PROJECT_ID
: the ID of your Google Cloud projectLOCATION
: the dataset locationDATASET_ID
: the FHIR store's parent datasetFHIR_STORE_ID
: the FHIR store IDRECOVERY_TIMESTAMP
: a recovery point within the last 21 days. Use the RFC 3339 format. Specify the time to the second and include a time zone, for example2015-02-07T13:28:17.239+02:00
or2017-01-01T00:00:00Z
.CLOUD_STORAGE_BUCKET
: the fully qualified URI to a Cloud Storage folder or bucket where output files are written
Request JSON body:
{ "rollbackTime": "RECOVERY_TIMESTAMP", "resultGcsBucket": "gs://CLOUD_STORAGE_BUCKET", "force": "false" }
To send your request, choose one of these options:
curl
Save the request body in a file named
request.json
. Run the following command in the terminal to create or overwrite this file in the current directory:cat > request.json << 'EOF' { "rollbackTime": "RECOVERY_TIMESTAMP", "resultGcsBucket": "gs://CLOUD_STORAGE_BUCKET", "force": "false" } EOF
Then execute the following command to send your REST request:
curl -X POST \
-H "Authorization: Bearer $(gcloud auth print-access-token)" \
-H "Content-Type: application/json; charset=utf-8" \
-d @request.json \
"https://healthcare.googleapis.com/v1/projects/PROJECT_ID/locations/LOCATION/datasets/DATASET_ID/fhirStores/FHIR_STORE_ID:rollback"PowerShell
Save the request body in a file named
request.json
. Run the following command in the terminal to create or overwrite this file in the current directory:@' { "rollbackTime": "RECOVERY_TIMESTAMP", "resultGcsBucket": "gs://CLOUD_STORAGE_BUCKET", "force": "false" } '@ | Out-File -FilePath request.json -Encoding utf8
Then execute the following command to send your REST request:
$cred = gcloud auth print-access-token
$headers = @{ "Authorization" = "Bearer $cred" }
Invoke-WebRequest `
-Method POST `
-Headers $headers `
-ContentType: "application/json; charset=utf-8" `
-InFile request.json `
-Uri "https://healthcare.googleapis.com/v1/projects/PROJECT_ID/locations/LOCATION/datasets/DATASET_ID/fhirStores/FHIR_STORE_ID:rollback" | Select-Object -Expand ContentAPIs Explorer
Copy the request body and open the method reference page. The APIs Explorer panel opens on the right side of the page. You can interact with this tool to send requests. Paste the request body in this tool, complete any other required fields, and click Execute.
OPERATION_ID
. You need this value in the next step.Use the
projects.locations.datasets.operations.get
method to get the status of the long-running operation.Before using any of the request data, make the following replacements:
PROJECT_ID
: the ID of your Google Cloud projectDATASET_ID
: the dataset IDLOCATION
: the dataset locationOPERATION_ID
: the ID returned from the long-running operation
To send your request, choose one of these options:
curl
Execute the following command:
curl -X GET \
-H "Authorization: Bearer $(gcloud auth print-access-token)" \
"https://healthcare.googleapis.com/v1/projects/PROJECT_ID/locations/LOCATION/datasets/DATASET_ID/operations/OPERATION_ID"PowerShell
Execute the following command:
$cred = gcloud auth print-access-token
$headers = @{ "Authorization" = "Bearer $cred" }
Invoke-WebRequest `
-Method GET `
-Headers $headers `
-Uri "https://healthcare.googleapis.com/v1/projects/PROJECT_ID/locations/LOCATION/datasets/DATASET_ID/operations/OPERATION_ID" | Select-Object -Expand ContentAPIs Explorer
Open the method reference page. The APIs Explorer panel opens on the right side of the page. You can interact with this tool to send requests. Complete any required fields and click Execute.
"done": true
, the long-running operation has finished.
View dry run output files
Each dry run outputs one or more files containing the IDs and types of the FHIR
resources to recover. The files are created in a subfolder in the rollback_resources
folder in the destination
Cloud Storage bucket. The subfolder name is the LRO ID returned in the
fhirStores.rollback
response. To view the files and ensure the recovery works
as expected, see
View object metadata.
The number of files is proportional to the number of recovered FHIR resources.
File names use the format trial-NUMBER-of-TOTAL_NUMBER.txt
,
where NUMBER
is the file number and TOTAL_NUMBER
is the total number of files.
Dry run output file schema
The output files from a dry run recovery use the schema shown in the following table:
RESOURCE_TYPE |
RESOURCE_ID |
TIMESTAMP |
---|---|---|
The FHIR resource type. | The FHIR resource ID. | The time when the FHIR resource was created or updated in the FHIR store. |
Recover in production
Before recovering in production, do a dry run and inspect the dry run output files to ensure the production recovery runs as expected.
The following samples show how to restore FHIR resources in production
using the fhirStores.rollback
method.
REST
Recover the FHIR resources.
Ensure the
force
field istrue
.Before using any of the request data, make the following replacements:
PROJECT_ID
: the ID of your Google Cloud projectLOCATION
: the dataset locationDATASET_ID
: the FHIR store's parent datasetFHIR_STORE_ID
: the FHIR store IDRECOVERY_TIMESTAMP
: a recovery point within the last 21 days. Use the RFC 3339 format. Specify the time to the second and include a time zone, for example2015-02-07T13:28:17.239+02:00
or2017-01-01T00:00:00Z
.CLOUD_STORAGE_BUCKET
: the fully qualified URI to a Cloud Storage folder or bucket where output files are written
Request JSON body:
{ "rollbackTime": "RECOVERY_TIMESTAMP", "resultGcsBucket": "gs://CLOUD_STORAGE_BUCKET", "force": "true" }
To send your request, choose one of these options:
curl
Save the request body in a file named
request.json
. Run the following command in the terminal to create or overwrite this file in the current directory:cat > request.json << 'EOF' { "rollbackTime": "RECOVERY_TIMESTAMP", "resultGcsBucket": "gs://CLOUD_STORAGE_BUCKET", "force": "true" } EOF
Then execute the following command to send your REST request:
curl -X POST \
-H "Authorization: Bearer $(gcloud auth print-access-token)" \
-H "Content-Type: application/json; charset=utf-8" \
-d @request.json \
"https://healthcare.googleapis.com/v1/projects/PROJECT_ID/locations/LOCATION/datasets/DATASET_ID/fhirStores/FHIR_STORE_ID:rollback"PowerShell
Save the request body in a file named
request.json
. Run the following command in the terminal to create or overwrite this file in the current directory:@' { "rollbackTime": "RECOVERY_TIMESTAMP", "resultGcsBucket": "gs://CLOUD_STORAGE_BUCKET", "force": "true" } '@ | Out-File -FilePath request.json -Encoding utf8
Then execute the following command to send your REST request:
$cred = gcloud auth print-access-token
$headers = @{ "Authorization" = "Bearer $cred" }
Invoke-WebRequest `
-Method POST `
-Headers $headers `
-ContentType: "application/json; charset=utf-8" `
-InFile request.json `
-Uri "https://healthcare.googleapis.com/v1/projects/PROJECT_ID/locations/LOCATION/datasets/DATASET_ID/fhirStores/FHIR_STORE_ID:rollback" | Select-Object -Expand ContentAPIs Explorer
Copy the request body and open the method reference page. The APIs Explorer panel opens on the right side of the page. You can interact with this tool to send requests. Paste the request body in this tool, complete any other required fields, and click Execute.
OPERATION_ID
. You need this value in the next step.Use the
projects.locations.datasets.operations.get
method to get the status of the long-running operation.Before using any of the request data, make the following replacements:
PROJECT_ID
: the ID of your Google Cloud projectDATASET_ID
: the dataset IDLOCATION
: the dataset locationOPERATION_ID
: the ID returned from the long-running operation
To send your request, choose one of these options:
curl
Execute the following command:
curl -X GET \
-H "Authorization: Bearer $(gcloud auth print-access-token)" \
"https://healthcare.googleapis.com/v1/projects/PROJECT_ID/locations/LOCATION/datasets/DATASET_ID/operations/OPERATION_ID"PowerShell
Execute the following command:
$cred = gcloud auth print-access-token
$headers = @{ "Authorization" = "Bearer $cred" }
Invoke-WebRequest `
-Method GET `
-Headers $headers `
-Uri "https://healthcare.googleapis.com/v1/projects/PROJECT_ID/locations/LOCATION/datasets/DATASET_ID/operations/OPERATION_ID" | Select-Object -Expand ContentAPIs Explorer
Open the method reference page. The APIs Explorer panel opens on the right side of the page. You can interact with this tool to send requests. Complete any required fields and click Execute.
"done": true
, the long-running operation has finished.
View production recovery output files
A production recovery outputs the following files. The files are created in a
subfolder in the rollback_resources
folder in the destination
Cloud Storage bucket. The subfolder name is the LRO ID returned in the
fhirStores.rollback
response. To view the files, see
View object metadata.
success-NUMBER-of-TOTAL_NUMBER.txt
: Contains successfully recovered FHIR resources.fail-NUMBER-of-TOTAL_NUMBER.txt
: Contains FHIR resources that failed to be recovered. An empty file is generated even if there are no failures.
In the file names, NUMBER
is the file number, and TOTAL_NUMBER
is the total number of files.
Production output file schema
The success and failure files from a production recovery use the following
schema. Error files contain an additional
ERROR_MESSAGE
column.
RESOURCE_TYPE |
RESOURCE_ID |
ROLLBACK_VERSION_ID |
NEW_VERSION_ID |
ERROR_MESSAGE (Error files only) |
---|---|---|---|---|
The FHIR resource type. | The FHIR resource ID. | The current version ID of the resource at the time when the recovery started. | The current version ID of the resource after the recovery. If the disableResourceVersioning is true , or if recovering a resource would delete the resource, ROLLBACK_VERSION_ID and NEW_VERSION_ID are empty. |
Error files only. Describes why the FHIR resource filed to be recovered. |
Use filters to recover specific FHIR resources
The following sections describe how to use filters to recover
FHIR resources based on a filter criteria.
You specify the filters in the RollbackFhirResourceFilteringFields
object when sending
a fhirStores.rollback
request.
You can combine filters or use them individually for multiple use cases, including the following:
- Recovering specific FHIR resources after accidental deletion while leaving others unchanged.
- Restoring a FHIR store to a state before a specific import operation imported certain FHIR resources.
Use a filter file
By default, PITR recovers all FHIR resources in a FHIR store. To recover
specific FHIR resources, specify the resource types and their resource IDs in a file,
and then upload the file to
Cloud Storage. Specify the location of the file in the
inputGcsObject
field.
To read a filter file from Cloud Storage, you must grant permissions to the Cloud Healthcare Service Agent service account. For more information, see Read filter files from Cloud Storage.
The filter file can have any extension. It must use the following schema, with one FHIR resource per line:
FHIR_RESOURCE_TYPE/FHIR_RESOURCE_ID
For example, to recover a Patient resource with the ID 8f25b0ac
and two
Observation resources with the IDs d507417e90e
and e9950d90e
, specify
the following in the filter file:
Patient/8f25b0ac
Observation/d507417e90e
Observation/e9950d90e
Use custom functions
The Cloud Healthcare API provides the following custom filtering functions.
You can combine the custom functions with the
rollbackTime
field to to apply an additional filter.
tag
Details Function syntax tag("system") = "code"
Description Filters FHIR resources based on the resourceMeta.tag
element.Arguments system
string
A URL that references a code system. For more information, see Using Codes in Resources.code
string
A value that identifies a concept as defined by the code system. For more information, see Using Codes in Resources.
extension_value_ts
Details Function syntax extension_value_ts("url")
Description Filters FHIR resources based on theurl
value in anextension
element whereurl
is a Unix timestamp. Supports the following comparison operators:=
!=
<
>
<=
>=
Arguments url
string
The canonical URL of a StructureDefinition resource that defines an extension. For example, in the followingextension
element, theurl
ishttp://hl7.org/fhir/StructureDefinition/timezone
:"extension" : [{ "url" : "http://hl7.org/fhir/StructureDefinition/timezone", "valueCode" : "America/New_York" }]
For more information, see Defining Extensions.
Filter by FHIR resource type
To filter FHIR resources
more broadly based only on the resource type, specify the resource types in the
types[]
array.
Filter by operation type
To filter for FHIR resources that were modified by a CREATE
, UPDATE
, or
DELETE
transaction,
specify a value in the ChangeType
enum.
For example,
to only recover FHIR resources that were deleted, specify the
DELETE
value.
If you specify CHANGE_TYPE_UNSPECIFIED
,
ALL
,
or you don't specify a value, all FHIR resources are recovered.
Exclude previous recoveries
To exclude previous recoveries when recovering FHIR resources, set the
excludeRollbacks
field to true
. You can exclude previous recoveries if the
recoveries worked correctly and you don't want to overwrite their changes.
You can also run multiple recoveries with overlapping timestamps.
Consider the following scenario:
- At
1:00
, you start a recovery with the recovery timestamp set to0:01
. At2:00
, the recovery operation deletes thePatient/1
andPatient/2
Patient resources in the FHIR store. The recovery operation ends at3:00
. Several days later, you run a recovery operation with the recovery timestamp set to
1:00
. By default, running the operation would result in the following:- Incorrectly recreating the
Patient/1
andPatient/2
Patient resources. - Correctly recovering FHIR resources created or updated after
3:00
.
- Incorrectly recreating the
To exclude the initial recovery operation that deleted
the Patient/1
and Patient/2
Patient resources, and avoid recreating them,
set excludeRollbacks
to true
.
Filter using long-running operation (LRO) IDs
If FHIR resources were modified by one or more long-running operations (LROs),
you can specify the LRO IDs in the operationIds
field
to recover the modified resources.
See Listing LROs for information on listing and viewing LRO IDs in a Cloud Healthcare API dataset.
Retry FHIR resources that failed to recover in production
If some FHIR resources failed a production recovery, you can retry the recovery. Use the generated production output file, to find the FHIR resources that failed. Specify the types of these FHIR resources and their IDs in a filter file, and run the recovery again.
Each time you run a recovery, the recovery is idempotent if you use the same configuration in each request and the timestamp is within the last 21 days.
Limitations
PITR doesn't enforce referential integrity, regardless of the
disableReferentialIntegrity
setting on the FHIR store. Restoring only some FHIR resources might leave the FHIR store in a state that violates referential integrity.PITR skips FHIR profile validation because the restored FHIR resources were validated when they were created or updated. If the FHIR store profile configuration changed, PITR might leave the FHIR store in a state that violates profile validation.
If the value of
rollbackTime
precedes the time when a FHIR resource was deleted in the FHIR store, the FHIR store must haveenableUpdateCreate
enabled or the resource won't be recovered.You can update a FHIR store or read and write data during a recovery, but you might see unexpected results depending on the recovery stage. For example, a read request might return a combination of recovered and non-recovered FHIR resources. If you update a resource, the recovery might overwrite the update.
PITR keeps FHIR resource history. Each restored resource gets a new current version and its history is retained.