Skip to content

Commit

Permalink
Merge pull request #119 from smartin015/edit_lan
Browse files Browse the repository at this point in the history
Full editable LAN queue items
  • Loading branch information
smartin015 committed Sep 3, 2022
2 parents 81be789 + c8c5730 commit e328592
Show file tree
Hide file tree
Showing 22 changed files with 631 additions and 425 deletions.
73 changes: 23 additions & 50 deletions continuousprint/api.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
from enum import Enum
from octoprint.access.permissions import Permissions, ADMIN_GROUP
from octoprint.server.util.flask import restricted_access
from .queues.lan import ValidationError
import flask
import json
from .storage import queries
Expand Down Expand Up @@ -174,58 +175,41 @@ def add_job(self):
self._get_queue(DEFAULT_QUEUE).add_job(data.get("name")).as_dict()
)

# PRIVATE API METHOD - may change without warning.
@octoprint.plugin.BlueprintPlugin.route("/set/mv", methods=["POST"])
@restricted_access
@cpq_permission(Permission.EDITJOB)
def mv_set(self):
self._get_queue(DEFAULT_QUEUE).mv_set(
int(flask.request.form["id"]),
int(
flask.request.form["after_id"]
), # Move to after this set (-1 for beginning of job)
int(
flask.request.form["dest_job"]
), # Move to this job (null for new job at end)
)
return json.dumps("ok")

# PRIVATE API METHOD - may change without warning.
@octoprint.plugin.BlueprintPlugin.route("/job/mv", methods=["POST"])
@restricted_access
@cpq_permission(Permission.EDITJOB)
def mv_job(self):
self._get_queue(DEFAULT_QUEUE).mv_job(
int(flask.request.form["id"]),
int(
flask.request.form["after_id"]
), # Move to after this job (-1 for beginning of queue)
)
return json.dumps("ok")
src_id = flask.request.form["id"]
after_id = flask.request.form["after_id"]
if after_id == "": # Treat empty string as 'none' i.e. front of queue
after_id = None
sq = self._get_queue(flask.request.form["src_queue"])
dq = self._get_queue(flask.request.form.get("dest_queue"))

# Transfer into dest queue first
if dq != sq:
try:
new_id = dq.import_job_from_view(sq.get_job_view(src_id))
except ValidationError as e:
return json.dumps(dict(error=str(e)))

# PRIVATE API METHOD - may change without warning.
@octoprint.plugin.BlueprintPlugin.route("/job/submit", methods=["POST"])
@restricted_access
@cpq_permission(Permission.ADDJOB)
def submit_job(self):
j = queries.getJob(int(flask.request.form["id"]))
# Submit to the queue and remove from its origin
err = self._get_queue(flask.request.form["queue"]).submit_job(j)
if err is None:
self._logger.debug(
self._get_queue(DEFAULT_QUEUE).remove_jobs(job_ids=[j.id])
)
return self._state_json()
else:
return json.dumps(dict(error=str(err)))
print("Imported job from view")
sq.remove_jobs([src_id])
src_id = new_id

# Finally, move the job
dq.mv_job(src_id, after_id)
return json.dumps("OK")

# PRIVATE API METHOD - may change without warning.
@octoprint.plugin.BlueprintPlugin.route("/job/edit", methods=["POST"])
@restricted_access
@cpq_permission(Permission.EDITJOB)
def edit_job(self):
data = json.loads(flask.request.form.get("json"))
return json.dumps(self._get_queue(DEFAULT_QUEUE).edit_job(data["id"], data))
q = self._get_queue(data["queue"])
return json.dumps(q.edit_job(data["id"], data))

# PRIVATE API METHOD - may change without warning.
@octoprint.plugin.BlueprintPlugin.route("/job/import", methods=["POST"])
Expand Down Expand Up @@ -270,17 +254,6 @@ def rm_job(self):
)
)

# PRIVATE API METHOD - may change without warning.
@octoprint.plugin.BlueprintPlugin.route("/set/rm", methods=["POST"])
@restricted_access
@cpq_permission(Permission.EDITJOB)
def rm_set(self):
return json.dumps(
self._get_queue(DEFAULT_QUEUE).rm_multi(
set_ids=flask.request.form.getlist("set_ids[]")
)
)

# PRIVATE API METHOD - may change without warning.
@octoprint.plugin.BlueprintPlugin.route("/job/reset", methods=["POST"])
@restricted_access
Expand Down
15 changes: 11 additions & 4 deletions continuousprint/driver.py
Original file line number Diff line number Diff line change
Expand Up @@ -78,12 +78,19 @@ def action(
# Given that some calls to action() come from a watchdog timer, we hold a mutex when performing the action
# so the state is updated in a thread safe way.
with self.mutex:
self._logger.debug(
f"{a.name}, {p.name}, path={path}, materials={materials}, bed_temp={bed_temp}"
)
now = time.time()
if self.idle_start_ts is None or self.idle_start_ts + 15 > now:
extra = (
f"(idle logs hidden after {self.idle_start_ts+15})"
if self.idle_start_ts is not None
else ""
)
self._logger.debug(
f"{a.name}, {p.name}, path={path}, materials={materials}, bed_temp={bed_temp} {extra}"
)

if p == Printer.IDLE and self.idle_start_ts is None:
self.idle_start_ts = time.time()
self.idle_start_ts = now
elif p != Printer.IDLE and self.idle_start_ts is not None:
self.idle_start_ts = None

Expand Down
17 changes: 8 additions & 9 deletions continuousprint/integration_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
from peewee import SqliteDatabase
from collections import defaultdict
from peerprint.lan_queue import LANPrintQueueBase
from peerprint.sync_objects_test import TestReplDict

# logging.basicConfig(level=logging.DEBUG)

Expand Down Expand Up @@ -183,11 +184,6 @@ def release(self, k):
self.locks.pop(k, None)


class LocalJobDict(dict):
def set(self, k, v, **kwargs):
self[k] = v


class TestLANQueue(IntegrationTest):
"""A simple in-memory integration test between DB storage layer, queuing layer, and driver."""

Expand All @@ -214,13 +210,14 @@ def setUp(self):
self.lq.ns, self.lq.addr, MagicMock(), logging.getLogger("lantestbase")
)
self.lq.lan.q.locks = LocalLockManager(dict(), "lq")
self.lq.lan.q.jobs = LocalJobDict()
self.lq.lan.q.jobs = TestReplDict(lambda a, b: None)
self.lq.lan.q.peers = dict()

def test_completes_job_in_order(self):
self.lq.lan.q.setJob(
"bsdf",
"uuid1",
dict(
id="uuid1",
name="j1",
created=0,
sets=[
Expand All @@ -238,8 +235,9 @@ def test_completes_job_in_order(self):
def test_multi_job(self):
for name in ("j1", "j2"):
self.lq.lan.q.setJob(
f"{name}_hash",
f"{name}_id",
dict(
id=f"{name}_id",
name=name,
created=0,
sets=[dict(path=f"{name}.gcode", count=1, remaining=1)],
Expand Down Expand Up @@ -288,7 +286,7 @@ def onupdate():
lq.ns, lq.addr, MagicMock(), logging.getLogger("lantestbase")
)
lq.lan.q.locks = LocalLockManager(self.locks, f"peer{i}")
lq.lan.q.jobs = LocalJobDict()
lq.lan.q.jobs = TestReplDict(lambda a, b: None)
lq.lan.q.peers = self.peers
if i > 0:
lq.lan.q.peers = self.peers[0][2].lan.q.peers
Expand All @@ -304,6 +302,7 @@ def test_ordered_acquisition(self):
lq1.lan.q.setJob(
f"{name}_hash",
dict(
id=f"{name}_hash",
name=name,
created=0,
sets=[
Expand Down
28 changes: 12 additions & 16 deletions continuousprint/queues/abstract.py
Original file line number Diff line number Diff line change
Expand Up @@ -67,40 +67,36 @@ def reset_jobs(self, job_ids) -> dict:
pass


class AbstractJobQueue(AbstractQueue):
"""LAN queues (potentially others in the future) act on whole jobs and do not allow
edits to inner data"""

@abstractmethod
def submit_job(self, j: JobView) -> bool:
pass


class AbstractEditableQueue(AbstractQueue):
"""Some queues (e.g. local to a single printer) are directly editable."""
"""Use for queues that are directly editable."""

@abstractmethod
def add_job(self, name="") -> JobView:
def mv_job(self, job_id, after_id):
pass

@abstractmethod
def add_set(self, job_id, data) -> SetView:
def edit_job(self, job_id, data):
pass

@abstractmethod
def mv_set(self, set_id, after_id, dest_job) -> SetView:
def get_job_view(self, job_id):
pass

@abstractmethod
def mv_job(self, job_id, after_id):
def import_job_from_view(self, job_view):
"""Imports a JobView into storage. Returns ID of the imported job"""
pass


class AbstractFactoryQueue(AbstractEditableQueue):
"""Use for queues where you can construct new jobs/sets"""

@abstractmethod
def edit_job(self, job_id, data):
def add_job(self, name="") -> JobView:
pass

@abstractmethod
def rm_multi(self, job_ids, set_ids) -> dict:
def add_set(self, job_id, data) -> SetView:
pass

@abstractmethod
Expand Down
Loading

0 comments on commit e328592

Please sign in to comment.