implement database migrations and add delivery_attempts and next_delivery_attempt_at columns to lxmf messages table

This commit is contained in:
liamcottle 2024-07-08 16:22:24 +12:00
commit 28e40cb002
2 changed files with 42 additions and 3 deletions

View file

@ -1,8 +1,24 @@
from datetime import datetime, timezone
from peewee import *
from playhouse.migrate import migrate as migrate_database, SqliteMigrator
latest_version = 2 # increment each time new database migrations are added
database = DatabaseProxy() # use a proxy object, as we will init real db client inside web.py
migrator = SqliteMigrator(database)
# migrates the database
def migrate(current_version):
# migrate to version 2
if current_version < 2:
migrate_database(
migrator.add_column("lxmf_messages", 'delivery_attempts', LxmfMessage.delivery_attempts),
migrator.add_column("lxmf_messages", 'next_delivery_attempt_at', LxmfMessage.next_delivery_attempt_at),
)
return latest_version
class BaseModel(Model):
@ -49,6 +65,8 @@ class LxmfMessage(BaseModel):
state = CharField() # state is converted from internal int to a human friendly string
progress = FloatField() # progress is converted from internal float 0.00-1.00 to float between 0.00/100 (2 decimal places)
is_incoming = BooleanField() # if true, we should ignore state, it's set to draft by default on incoming messages
delivery_attempts = IntegerField(default=0) # how many times delivery has been attempted for this message
next_delivery_attempt_at = FloatField(null=True) # timestamp of when the message will attempt delivery again
title = TextField()
content = TextField()
fields = TextField() # json string

27
web.py
View file

@ -57,6 +57,9 @@ class ReticulumMeshChat:
self.database_path = os.path.join(self.storage_path, "database.db")
lxmf_router_path = os.path.join(self.storage_path, "lxmf_router")
# check if database already exists, before initialization
database_already_exists = os.path.exists(self.database_path)
# init database
sqlite_database = SqliteDatabase(self.database_path)
database.database.initialize(sqlite_database)
@ -69,6 +72,22 @@ class ReticulumMeshChat:
database.LxmfConversationReadState,
])
# init config
self.config = Config()
# if database already existed before init, and we don't have a previous version set, we are on version 1
if database_already_exists and self.config.database_version.get() is None:
self.config.database_version.set(1)
# if database didn't already exist, it was just fully migrated when it was created, so set the current version
if not database_already_exists:
self.config.database_version.set(database.latest_version)
# migrate database
current_database_version = self.config.database_version.get()
migrated_database_version = database.migrate(current_version=current_database_version)
self.config.database_version.set(migrated_database_version)
# vacuum database on start to shrink its file size
sqlite_database.execute_sql("VACUUM")
@ -77,9 +96,6 @@ class ReticulumMeshChat:
.where(database.LxmfMessage.state == "outbound")
.orwhere(database.LxmfMessage.state == "sending").execute())
# init config
self.config = Config()
# init reticulum
self.reticulum = RNS.Reticulum(reticulum_config_dir)
self.identity = identity
@ -1298,6 +1314,8 @@ class ReticulumMeshChat:
"is_incoming": lxmf_message.incoming,
"state": self.convert_lxmf_state_to_string(lxmf_message),
"progress": progress_percentage,
"delivery_attempts": lxmf_message.delivery_attempts,
"next_delivery_attempt_at": getattr(lxmf_message, "next_delivery_attempt", None), # attribute may not exist yet
"title": lxmf_message.title.decode('utf-8'),
"content": lxmf_message.content.decode('utf-8'),
"fields": fields,
@ -1386,6 +1404,8 @@ class ReticulumMeshChat:
"is_incoming": lxmf_message_dict["is_incoming"],
"state": lxmf_message_dict["state"],
"progress": lxmf_message_dict["progress"],
"delivery_attempts": lxmf_message_dict["delivery_attempts"],
"next_delivery_attempt_at": lxmf_message_dict["next_delivery_attempt_at"],
"title": lxmf_message_dict["title"],
"content": lxmf_message_dict["content"],
"fields": json.dumps(lxmf_message_dict["fields"]),
@ -1719,6 +1739,7 @@ class Config:
Config.set(self.key, str(value))
# all possible config items
database_version = IntConfig("database_version", None)
display_name = StringConfig("display_name", "Anonymous Peer")
auto_announce_enabled = BoolConfig("auto_announce_enabled", False)
auto_announce_interval_seconds = IntConfig("auto_announce_interval_seconds", 0)