This commit is contained in:
Inex Code 2022-08-02 23:30:03 +03:00
parent b965ffd96a
commit 5e62798fde
4 changed files with 53 additions and 30 deletions

View file

@ -25,6 +25,12 @@ class ApiJob:
@strawberry.type @strawberry.type
class JobSubscription: class JobSubscription:
@strawberry.subscription
async def count(self, target: int = 100) -> AsyncGenerator[int, None]:
for i in range(target):
yield i
await asyncio.sleep(0.5)
@strawberry.subscription() @strawberry.subscription()
async def job_subscription(self) -> AsyncGenerator[typing.List[ApiJob], None]: async def job_subscription(self) -> AsyncGenerator[typing.List[ApiJob], None]:
is_updated = True is_updated = True
@ -34,7 +40,7 @@ class JobSubscription:
is_updated = True is_updated = True
print("Subscribing to job updates...") print("Subscribing to job updates...")
Jobs().add_observer(callback) Jobs.get_instance().add_observer(callback)
yield [ yield [
ApiJob( ApiJob(
name=job.name, name=job.name,
@ -48,7 +54,7 @@ class JobSubscription:
error=job.error, error=job.error,
result=job.result, result=job.result,
) )
for job in Jobs().get_jobs() for job in Jobs.get_instance().get_jobs()
] ]
while True: while True:
if is_updated: if is_updated:
@ -66,5 +72,5 @@ class JobSubscription:
error=job.error, error=job.error,
result=job.result, result=job.result,
) )
for job in Jobs().get_jobs() for job in Jobs.get_instance().get_jobs()
] ]

View file

@ -92,6 +92,10 @@ class Jobs:
""" """
if Jobs.__instance is None: if Jobs.__instance is None:
Jobs() Jobs()
if Jobs.__instance is None:
raise Exception("Couldn't init Jobs singleton!")
return Jobs.__instance
else:
return Jobs.__instance return Jobs.__instance
def __init__(self): def __init__(self):
@ -102,7 +106,20 @@ class Jobs:
raise Exception("This class is a singleton!") raise Exception("This class is a singleton!")
else: else:
Jobs.__instance = self Jobs.__instance = self
self.jobs = [] self.jobs = [
Job(
name="Init job",
description="Initial job",
status=JobStatus.FINISHED,
status_text="",
progress=100,
created_at=datetime.datetime.now(),
updated_at=datetime.datetime.now(),
finished_at=datetime.datetime.now(),
error=None,
result=None,
)
]
# Observers of the jobs list. # Observers of the jobs list.
self.observers = [] self.observers = []

View file

@ -5,7 +5,7 @@ from selfprivacy_api.jobs import JobStatus, Jobs
@huey.task() @huey.task()
def test_job(): def test_job():
job = Jobs().add( job = Jobs.get_instance().add(
name="Test job", name="Test job",
description="This is a test job.", description="This is a test job.",
status=JobStatus.CREATED, status=JobStatus.CREATED,
@ -13,42 +13,42 @@ def test_job():
progress=0, progress=0,
) )
time.sleep(5) time.sleep(5)
Jobs().update( Jobs.get_instance().update(
job=job, job=job,
status=JobStatus.RUNNING, status=JobStatus.RUNNING,
status_text="Performing pre-move checks...", status_text="Performing pre-move checks...",
progress=5, progress=5,
) )
time.sleep(5) time.sleep(5)
Jobs().update( Jobs.get_instance().update(
job=job, job=job,
status=JobStatus.RUNNING, status=JobStatus.RUNNING,
status_text="Performing pre-move checks...", status_text="Performing pre-move checks...",
progress=10, progress=10,
) )
time.sleep(5) time.sleep(5)
Jobs().update( Jobs.get_instance().update(
job=job, job=job,
status=JobStatus.RUNNING, status=JobStatus.RUNNING,
status_text="Performing pre-move checks...", status_text="Performing pre-move checks...",
progress=15, progress=15,
) )
time.sleep(5) time.sleep(5)
Jobs().update( Jobs.get_instance().update(
job=job, job=job,
status=JobStatus.RUNNING, status=JobStatus.RUNNING,
status_text="Performing pre-move checks...", status_text="Performing pre-move checks...",
progress=20, progress=20,
) )
time.sleep(5) time.sleep(5)
Jobs().update( Jobs.get_instance().update(
job=job, job=job,
status=JobStatus.RUNNING, status=JobStatus.RUNNING,
status_text="Performing pre-move checks...", status_text="Performing pre-move checks...",
progress=25, progress=25,
) )
time.sleep(5) time.sleep(5)
Jobs().update( Jobs.get_instance().update(
job=job, job=job,
status=JobStatus.FINISHED, status=JobStatus.FINISHED,
status_text="Job finished.", status_text="Job finished.",

View file

@ -123,7 +123,7 @@ class Nextcloud(Service):
return super().get_dns_records() return super().get_dns_records()
def move_to_volume(self, volume: BlockDevice): def move_to_volume(self, volume: BlockDevice):
job = Jobs().add( job = Jobs.get_instance().add(
name="services.nextcloud.move", name="services.nextcloud.move",
description=f"Moving Nextcloud to volume {volume.name}", description=f"Moving Nextcloud to volume {volume.name}",
) )
@ -134,14 +134,14 @@ class Nextcloud(Service):
@huey.task() @huey.task()
def move_nextcloud(nextcloud: Nextcloud, volume: BlockDevice, job: Job): def move_nextcloud(nextcloud: Nextcloud, volume: BlockDevice, job: Job):
"""Move Nextcloud to another volume.""" """Move Nextcloud to another volume."""
job = Jobs().update( job = Jobs.get_instance().update(
job=job, job=job,
status_text="Performing pre-move checks...", status_text="Performing pre-move checks...",
status=JobStatus.RUNNING, status=JobStatus.RUNNING,
) )
with ReadUserData() as user_data: with ReadUserData() as user_data:
if not user_data.get("useBinds", False): if not user_data.get("useBinds", False):
Jobs().update( Jobs.get_instance().update(
job=job, job=job,
status=JobStatus.ERROR, status=JobStatus.ERROR,
error="Server is not using binds.", error="Server is not using binds.",
@ -150,7 +150,7 @@ def move_nextcloud(nextcloud: Nextcloud, volume: BlockDevice, job: Job):
# Check if we are on the same volume # Check if we are on the same volume
old_location = nextcloud.get_location() old_location = nextcloud.get_location()
if old_location == volume.name: if old_location == volume.name:
Jobs().update( Jobs.get_instance().update(
job=job, job=job,
status=JobStatus.ERROR, status=JobStatus.ERROR,
error="Nextcloud is already on this volume.", error="Nextcloud is already on this volume.",
@ -158,7 +158,7 @@ def move_nextcloud(nextcloud: Nextcloud, volume: BlockDevice, job: Job):
return return
# Check if there is enough space on the new volume # Check if there is enough space on the new volume
if volume.fsavail < nextcloud.get_storage_usage(): if volume.fsavail < nextcloud.get_storage_usage():
Jobs().update( Jobs.get_instance().update(
job=job, job=job,
status=JobStatus.ERROR, status=JobStatus.ERROR,
error="Not enough space on the new volume.", error="Not enough space on the new volume.",
@ -166,7 +166,7 @@ def move_nextcloud(nextcloud: Nextcloud, volume: BlockDevice, job: Job):
return return
# Make sure the volume is mounted # Make sure the volume is mounted
if f"/volumes/{volume.name}" not in volume.mountpoints: if f"/volumes/{volume.name}" not in volume.mountpoints:
Jobs().update( Jobs.get_instance().update(
job=job, job=job,
status=JobStatus.ERROR, status=JobStatus.ERROR,
error="Volume is not mounted.", error="Volume is not mounted.",
@ -174,7 +174,7 @@ def move_nextcloud(nextcloud: Nextcloud, volume: BlockDevice, job: Job):
return return
# Make sure current actual directory exists # Make sure current actual directory exists
if not pathlib.Path(f"/volumes/{old_location}/nextcloud").exists(): if not pathlib.Path(f"/volumes/{old_location}/nextcloud").exists():
Jobs().update( Jobs.get_instance().update(
job=job, job=job,
status=JobStatus.ERROR, status=JobStatus.ERROR,
error="Nextcloud is not found.", error="Nextcloud is not found.",
@ -182,7 +182,7 @@ def move_nextcloud(nextcloud: Nextcloud, volume: BlockDevice, job: Job):
return return
# Stop Nextcloud # Stop Nextcloud
Jobs().update( Jobs.get_instance().update(
job=job, job=job,
status=JobStatus.RUNNING, status=JobStatus.RUNNING,
status_text="Stopping Nextcloud...", status_text="Stopping Nextcloud...",
@ -196,7 +196,7 @@ def move_nextcloud(nextcloud: Nextcloud, volume: BlockDevice, job: Job):
break break
time.sleep(1) time.sleep(1)
else: else:
Jobs().update( Jobs.get_instance().update(
job=job, job=job,
status=JobStatus.ERROR, status=JobStatus.ERROR,
error="Nextcloud did not stop in 30 seconds.", error="Nextcloud did not stop in 30 seconds.",
@ -204,7 +204,7 @@ def move_nextcloud(nextcloud: Nextcloud, volume: BlockDevice, job: Job):
return return
# Unmount old volume # Unmount old volume
Jobs().update( Jobs.get_instance().update(
job=job, job=job,
status_text="Unmounting old folder...", status_text="Unmounting old folder...",
status=JobStatus.RUNNING, status=JobStatus.RUNNING,
@ -213,14 +213,14 @@ def move_nextcloud(nextcloud: Nextcloud, volume: BlockDevice, job: Job):
try: try:
subprocess.run(["umount", "/var/lib/nextcloud"], check=True) subprocess.run(["umount", "/var/lib/nextcloud"], check=True)
except subprocess.CalledProcessError: except subprocess.CalledProcessError:
Jobs().update( Jobs.get_instance().update(
job=job, job=job,
status=JobStatus.ERROR, status=JobStatus.ERROR,
error="Unable to unmount old volume.", error="Unable to unmount old volume.",
) )
return return
# Move data to new volume and set correct permissions # Move data to new volume and set correct permissions
Jobs().update( Jobs.get_instance().update(
job=job, job=job,
status_text="Moving data to new volume...", status_text="Moving data to new volume...",
status=JobStatus.RUNNING, status=JobStatus.RUNNING,
@ -230,7 +230,7 @@ def move_nextcloud(nextcloud: Nextcloud, volume: BlockDevice, job: Job):
f"/volumes/{old_location}/nextcloud", f"/volumes/{volume.name}/nextcloud" f"/volumes/{old_location}/nextcloud", f"/volumes/{volume.name}/nextcloud"
) )
Jobs().update( Jobs.get_instance().update(
job=job, job=job,
status_text="Making sure Nextcloud owns its files...", status_text="Making sure Nextcloud owns its files...",
status=JobStatus.RUNNING, status=JobStatus.RUNNING,
@ -248,7 +248,7 @@ def move_nextcloud(nextcloud: Nextcloud, volume: BlockDevice, job: Job):
) )
except subprocess.CalledProcessError as error: except subprocess.CalledProcessError as error:
print(error.output) print(error.output)
Jobs().update( Jobs.get_instance().update(
job=job, job=job,
status=JobStatus.RUNNING, status=JobStatus.RUNNING,
error="Unable to set ownership of new volume. Nextcloud may not be able to access its files. Continuing anyway.", error="Unable to set ownership of new volume. Nextcloud may not be able to access its files. Continuing anyway.",
@ -256,7 +256,7 @@ def move_nextcloud(nextcloud: Nextcloud, volume: BlockDevice, job: Job):
return return
# Mount new volume # Mount new volume
Jobs().update( Jobs.get_instance().update(
job=job, job=job,
status_text="Mounting Nextcloud data...", status_text="Mounting Nextcloud data...",
status=JobStatus.RUNNING, status=JobStatus.RUNNING,
@ -274,7 +274,7 @@ def move_nextcloud(nextcloud: Nextcloud, volume: BlockDevice, job: Job):
) )
except subprocess.CalledProcessError as error: except subprocess.CalledProcessError as error:
print(error.output) print(error.output)
Jobs().update( Jobs.get_instance().update(
job=job, job=job,
status=JobStatus.ERROR, status=JobStatus.ERROR,
error="Unable to mount new volume.", error="Unable to mount new volume.",
@ -282,7 +282,7 @@ def move_nextcloud(nextcloud: Nextcloud, volume: BlockDevice, job: Job):
return return
# Update userdata # Update userdata
Jobs().update( Jobs.get_instance().update(
job=job, job=job,
status_text="Finishing move...", status_text="Finishing move...",
status=JobStatus.RUNNING, status=JobStatus.RUNNING,
@ -294,7 +294,7 @@ def move_nextcloud(nextcloud: Nextcloud, volume: BlockDevice, job: Job):
user_data["nextcloud"]["location"] = volume.name user_data["nextcloud"]["location"] = volume.name
# Start Nextcloud # Start Nextcloud
nextcloud.start() nextcloud.start()
Jobs().update( Jobs.get_instance().update(
job=job, job=job,
status=JobStatus.FINISHED, status=JobStatus.FINISHED,
result="Nextcloud moved successfully.", result="Nextcloud moved successfully.",