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

feat: add support for Point In Time Recovery (PITR) #148

Merged
merged 8 commits into from Feb 22, 2021
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
28 changes: 26 additions & 2 deletions google/cloud/spanner_v1/backup.py
Expand Up @@ -51,14 +51,23 @@ class Backup(object):
:param expire_time: (Optional) The expire time that will be used to
create the backup. Required if the create method
needs to be called.

:type version_time: :class:`datetime.datetime`
:param version_time: (Optional) The version time that was specified for
the externally consistent copy of the database. If
not present, it is the same as the `create_time` of
the backup.
"""

def __init__(self, backup_id, instance, database="", expire_time=None):
def __init__(
self, backup_id, instance, database="", expire_time=None, version_time=None
):
self.backup_id = backup_id
self._instance = instance
self._database = database
self._expire_time = expire_time
self._create_time = None
self._version_time = version_time
self._size_bytes = None
self._state = None
self._referencing_databases = None
Expand Down Expand Up @@ -109,6 +118,16 @@ def create_time(self):
"""
return self._create_time

@property
def version_time(self):
"""Version time of this backup.

:rtype: :class:`datetime.datetime`
:returns: a datetime object representing the version time of
this backup
"""
return self._version_time

@property
def size_bytes(self):
"""Size of this backup in bytes.
Expand Down Expand Up @@ -190,7 +209,11 @@ def create(self):
raise ValueError("database not set")
api = self._instance._client.database_admin_api
metadata = _metadata_with_prefix(self.name)
backup = BackupPB(database=self._database, expire_time=self.expire_time,)
backup = BackupPB(
database=self._database,
expire_time=self.expire_time,
version_time=self.version_time,
)

future = api.create_backup(
parent=self._instance.name,
Expand Down Expand Up @@ -228,6 +251,7 @@ def reload(self):
self._database = pb.database
self._expire_time = pb.expire_time
self._create_time = pb.create_time
self._version_time = pb.version_time
self._size_bytes = pb.size_bytes
self._state = BackupPB.State(pb.state)
self._referencing_databases = pb.referencing_databases
Expand Down
23 changes: 23 additions & 0 deletions google/cloud/spanner_v1/database.py
Expand Up @@ -107,6 +107,8 @@ def __init__(self, database_id, instance, ddl_statements=(), pool=None):
self._state = None
self._create_time = None
self._restore_info = None
self._version_retention_period = None
self._earliest_version_time = None

if pool is None:
pool = BurstyPool()
Expand Down Expand Up @@ -204,6 +206,25 @@ def restore_info(self):
"""
return self._restore_info

@property
def version_retention_period(self):
"""The period in which Cloud Spanner retains all versions of data
for the database.

:rtype: str
:returns: a string representing the duration of the version retention period
"""
return self._version_retention_period

@property
def earliest_version_time(self):
"""The earliest time at which older versions of the data can be read.

:rtype: :class:`datetime.datetime`
:returns: a datetime object representing the earliest version time
"""
return self._earliest_version_time

@property
def ddl_statements(self):
"""DDL Statements used to define database schema.
Expand Down Expand Up @@ -313,6 +334,8 @@ def reload(self):
self._state = DatabasePB.State(response.state)
self._create_time = response.create_time
self._restore_info = response.restore_info
self._version_retention_period = response.version_retention_period
self._earliest_version_time = response.earliest_version_time

def update_ddl(self, ddl_statements, operation_id=""):
"""Update DDL for this database.
Expand Down
22 changes: 19 additions & 3 deletions google/cloud/spanner_v1/instance.py
Expand Up @@ -400,7 +400,7 @@ def list_databases(self, page_size=None):
)
return page_iter

def backup(self, backup_id, database="", expire_time=None):
def backup(self, backup_id, database="", expire_time=None, version_time=None):
"""Factory to create a backup within this instance.

:type backup_id: str
Expand All @@ -415,13 +415,29 @@ def backup(self, backup_id, database="", expire_time=None):
:param expire_time:
Optional. The expire time that will be used when creating the backup.
Required if the create method needs to be called.

:type version_time: :class:`datetime.datetime`
:param version_time:
Optional. The version time that will be used to create the externally
consistent copy of the database. If not present, it is the same as
the `create_time` of the backup.
"""
try:
return Backup(
backup_id, self, database=database.name, expire_time=expire_time
backup_id,
self,
database=database.name,
expire_time=expire_time,
version_time=version_time,
)
except AttributeError:
return Backup(backup_id, self, database=database, expire_time=expire_time)
return Backup(
backup_id,
self,
database=database,
expire_time=expire_time,
version_time=version_time,
)

def list_backups(self, filter_="", page_size=None):
"""List backups for the instance.
Expand Down