Skip to content

Commit

Permalink
huey tasks FE improvements
Browse files Browse the repository at this point in the history
  • Loading branch information
andreipradan committed Feb 8, 2024
1 parent e5224d9 commit 01bad7a
Show file tree
Hide file tree
Showing 5 changed files with 52 additions and 35 deletions.
2 changes: 1 addition & 1 deletion backend/clients/prediction.py
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ def train(cls, df, logger):
log_status("train", accuracy=f"{accuracy:.2f}")
if accuracy < 0.95:
error = f"Insufficient accuracy: {accuracy:.2f}"
log_status("train", status=SIGNAL_ERROR, error=error)
log_status("train", status=SIGNAL_ERROR, errors=[error])
raise ValueError(error)

prefix = f"{timezone.now():%Y_%m_%d_%H_%M_%S}_{accuracy}"
Expand Down
23 changes: 12 additions & 11 deletions backend/core/tasks.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,28 +5,29 @@
redis_client = HUEY.storage.redis_client()


def log_status(key, **kwargs):
def log_status(key, errors=None, **kwargs):
new_event = {"timestamp": timezone.now().isoformat(), **kwargs}
errors = errors or []

details = json.loads(redis_client.get(key) or "{}")
if not details:
details = {"history": [new_event], **new_event}
details = {"errors": errors, "history": [new_event], **new_event}
else:
if "errors" in details:
details["errors"] = [
*new_event.pop("errors", []),
*details["errors"][:30],
]
details.update(new_event)
details["history"] = [new_event, *details["history"][:1000]]
if "errors" not in details:
details["errors"] = errors
else:
details["errors"] = [*errors, *details["errors"][:29]]
details["history"] = [new_event, *details["history"][:999]]
redis_client.set(key, json.dumps(details))
return details


@HUEY.signal()
def signal_handler(signal, task, exc=None):
now = timezone.now().isoformat()
kwargs = {"errors": [], "id": task.id, "status": signal, "timestamp": now}
errors = []
kwargs = {"id": task.id, "status": signal, "timestamp": now}
if exc:
kwargs["errors"].append({"msg": str(exc), "timestamp": now})
log_status(task.name, **kwargs)
errors.append({"timestamp": now, "msg": str(exc)})
log_status(task.name, errors, **kwargs)
2 changes: 1 addition & 1 deletion backend/finance/tasks.py
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ def train(logger):
)
count = qs.count()
if not count:
log_status("train", status=SIGNAL_ERROR, error="No trained data")
log_status("train", status=SIGNAL_ERROR, errors=["No trained data"])
raise ValueError("No trained data")
log_status("train", count=count)
logger.info("Training on %d confirmed transactions...", count)
Expand Down
3 changes: 3 additions & 0 deletions frontend/src/app/App.scss
Original file line number Diff line number Diff line change
Expand Up @@ -95,4 +95,7 @@
}
.min-vw-75 {
min-width: 75vw;
}
.min-vw-50 {
min-width: 50vw;
}
57 changes: 35 additions & 22 deletions frontend/src/app/tasks/Tasks.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,16 @@ import { selectItem } from "../../redux/tasksSlice";
import Errors from "../shared/Errors";
import TasksApi from "../../api/tasks";

const parseStatus = status => status === "complete"
const parseStatus = status => {
const icon = status === "complete"
? "✅"
: status === "executing"
? "⚙️"
: ["canceled", "error", "interrupted"].includes(status)
? `${status} ❌`
: status
? "❌"
: "❓"
return `${capitalize(status)} ${icon}`
}

const Tasks = () => {
const dispatch = useDispatch();
Expand All @@ -25,7 +28,9 @@ const Tasks = () => {
const [taskErrorsOpen, setTaskErrorsOpen] = useState(false)
const [taskHistoryOpen, setTaskHistoryOpen] = useState(false)

useEffect(() => !results && dispatch(TasksApi.getList(token)), [])
useEffect(() => {
if (!results) dispatch(TasksApi.getList(token))
}, [])

return (
<div>
Expand Down Expand Up @@ -66,10 +71,11 @@ const Tasks = () => {
<tr>
<th>#</th>
<th>Task</th>
<th>Is periodic?</th>
<th className="text-center">Is periodic?</th>
<th>Status</th>
<th>Last Run</th>
{/*<th>Actions</th>*/}
<th>Events</th>
<th>Errors</th>
</tr>
</thead>
<tbody>
Expand All @@ -84,22 +90,24 @@ const Tasks = () => {
>
<td>{i + 1}</td>
<td>{task.app}.{task.name}</td>
<td>{task.is_periodic ? <i className="mdi mdi-check text-success" /> : null}</td>
<td className="text-center">{task.is_periodic ? <i className="mdi mdi-check text-success" /> : null}</td>
{
task.history?.length
? <>
<td className={`text-${task.status === "error" ? 'danger' : task.status === "executing" ? 'warning' : 'success'}`}>{task.status ? capitalize(task.status) : "-"}</td>
<td>{new Date(task.timestamp).toLocaleString()}</td>
<td>{task.history.length}</td>
<td>{task.errors?.length}</td>
</>
: <td colSpan={2}>Didn't run</td>
: <td colSpan={4} className="text-center">Didn't run</td>
}
</tr>
)
: <tr>
<td colSpan={5}>No crons available</td>
<td colSpan={7}>No tasks available</td>
</tr>
: <tr>
<td colSpan={6}>
<td colSpan={8}>
<ColorRing
width="100%"
radius="9"
Expand All @@ -116,28 +124,33 @@ const Tasks = () => {
dispatch(selectItem(null))
setTaskErrorsOpen(false)
setTaskHistoryOpen(false)
}}>
}}
dialogClassName="min-vw-50"

>
<Modal.Header closeButton>
<Modal.Title>
<div className="row">
<div className="col-lg-12 stretch-card">
{selectedItem?.name}
</div>
</div>
<p className="text-muted mt-0 mb-0">App: {selectedItem?.app} </p>
<p
className="text-muted mt-0 mb-0">App: {selectedItem?.app} </p>
{
selectedItem?.timestamp
? <p className="text-muted mt-0 mb-0">Last run: {selectedItem?.timestamp ? new Date(selectedItem.timestamp).toLocaleString() : null} </p>
? <p className="text-muted mt-0 mb-0">Last
run: {selectedItem?.timestamp ? new Date(selectedItem.timestamp).toLocaleString() : null} </p>
: null
}

<p className="text-muted mt-0 mb-0">ID: {selectedItem?.id} </p>
</Modal.Title>
</Modal.Header>
<Modal.Body>
<ul className="list-unstyled">
{
selectedItem
? Object.keys(selectedItem).filter(k => !["timestamp", "name", "app"].includes(k)).map((k, i) =>
? Object.keys(selectedItem).filter(k => !["timestamp", "name", "app", "id"].includes(k)).map((k, i) =>
["errors", "history"].includes(k)
? <li key={i}>
{
Expand All @@ -151,17 +164,15 @@ const Tasks = () => {
{
selectedItem[k].map((h, i) =>
<li key={i} className="pl-4 mt-1">
<i className="text-primary mdi mdi-chevron-right"></i>&nbsp;
<i className="text-secondary mdi mdi-arrow-right mr-1"/>
{
Object.keys(h).map(hkey =>
Object.keys(h).filter(k => k !== "id").map(hkey =>
hkey === "timestamp"
? new Date(h[hkey]).toLocaleString()
: hkey === "status"
? parseStatus(h[hkey])
: hkey === "id"
? `[${h[hkey].slice(0, 3)}..${h[hkey].slice(h[hkey].length - 3, h[hkey].length)}]`
: h[hkey]
).join(" ")
: h[hkey]
).join(" - ")
}
</li>
)
Expand All @@ -178,7 +189,9 @@ const Tasks = () => {
<i className="mdi mdi-close"/>
}
</li>
: <li key={i}>{capitalize(k)}: {selectedItem[k]}</li>
: k === "status"
? <li key={i}>Status: {parseStatus(selectedItem[k])}</li>
: <li key={i}>{capitalize(k)}: {selectedItem[k]}</li>
)
: null
}
Expand Down

0 comments on commit 01bad7a

Please sign in to comment.