backup: Rely solely on backup.lock and do not cache writes

Caching writes was causing us some issues if the startup of
`lightningd` didn't complete, i.e., the writes would happen on the
live DB, but we'd forget about them. Since we have the backup.lock
file in same directory as the plugin is running in, we no longer have
to defer the writes. This hugely simplifies our logic.

Fixes #155

Changelog-Fixed: backup: The plugin doesn't lose sync anymore if the startup is interrupted
This commit is contained in:
Christian Decker
2020-11-11 16:25:19 +01:00
parent 630d385a0b
commit f34787d065
2 changed files with 23 additions and 60 deletions

View File

@@ -289,52 +289,14 @@ def check_first_write(plugin, data_version):
@plugin.hook('db_write')
def on_db_write(writes, data_version, plugin, **kwargs):
change = Change(data_version, None, writes)
if not hasattr(plugin, 'backend'):
plugin.early_writes.append(change)
return {"result": "continue"}
else:
return apply_write(plugin, change)
def apply_write(plugin, change):
if not plugin.initialized:
assert(check_first_write(plugin, change.version))
plugin.initialized = True
if plugin.backend.add_change(change):
return {"result": "continue"}
@plugin.init()
def on_init(options: Mapping[str, str], plugin: Plugin, **kwargs):
# Reach into the DB and
configs = plugin.rpc.listconfigs()
plugin.db_path = configs['wallet']
destination = options['backup-destination']
# Ensure that we don't inadventently switch the destination
if not os.path.exists("backup.lock"):
print("Files in the current directory {}".format(", ".join(os.listdir("."))))
kill("Could not find backup.lock in the lightning-dir, have you initialized using the backup-cli utility?")
d = json.load(open("backup.lock", 'r'))
if destination is None or destination == 'null':
destination = d['backend_url']
elif destination != d['backend_url']:
kill(
"The destination specified as option does not match the one "
"specified in backup.lock. Please check your settings"
)
if not plugin.db_path.startswith('sqlite3'):
kill("The backup plugin only works with the sqlite3 database.")
plugin.backend = get_backend(destination, require_init=True)
for c in plugin.early_writes:
apply_write(plugin, c)
else:
kill("Could not append DB change to the backup. Need to shutdown!")
def kill(message: str):
@@ -356,11 +318,6 @@ def kill(message: str):
time.sleep(30)
def preflight(plugin: Plugin):
"""Perform some preflight checks.
"""
if not os.path.exists("backup.lock"):
kill("Could not find backup.lock in the lightning-dir")
plugin.add_option(
'backup-destination', None,
@@ -369,8 +326,12 @@ plugin.add_option(
if __name__ == "__main__":
preflight(plugin)
# Did we perform the version check of backend versus the first write?
# Did we perform the first write check?
plugin.initialized = False
plugin.early_writes = []
if not os.path.exists("backup.lock"):
kill("Could not find backup.lock in the lightning-dir")
d = json.load(open("backup.lock", 'r'))
destination = d['backend_url']
plugin.backend = get_backend(destination, require_init=True)
plugin.run()