UNPKG

ah-resque-ui

Version:

A resque administration website for actionhero

241 lines (220 loc) 6.74 kB
import React, { useState, useEffect } from "react"; import { ButtonToolbar, Button, Table, Modal, Row, Col } from "react-bootstrap"; import { Link } from "react-router-dom"; import Page from "../layouts/page"; import Pagination from "../components/pagination"; function FailedPage({ client, history, match }) { const [data, setData] = useState({ failed: [], counts: { failed: 0 }, focusedException: { exception: "", queue: "", worker: "", error: "", payload: { args: {} }, renderedStack: "", }, perPage: 15, showModal: false, page: parseInt(match.params.page || 0), }); useEffect(() => { data.page = parseInt(match.params.page || 0); setData({ ...data }); }, [match.params]); useEffect(() => { loadData(); }, [data.page]); async function loadData() { const response = await client.action( { start: data.page * data.perPage, stop: data.page * data.perPage + (data.perPage - 1), }, "/api/1/resque/resqueFailed" ); data.failed = response.failed; setData({ ...data }); await loadFailedCount(); } async function loadFailedCount() { const response = await client.action({}, "/api/1/resque/resqueFailedCount"); data.counts = { failed: response.failedCount }; setData({ ...data }); } async function removeFailedJob(index) { await client.action({ id: index }, "/api/1/resque/removeFailed", "POST"); await loadData(); } async function retryFailedJob(index) { await client.action( { id: index }, "/api/1/resque/retryAndRemoveFailed", "POST" ); await loadData(); } async function removeAllFailedJobs() { if (window.confirm("Are you sure?")) { await client.action({}, "/api/1/resque/removeAllFailed", "POST"); await loadData(); } } async function retryAllFailedJobs() { if (window.confirm("Are you sure?")) { await client.action({}, "/api/1/resque/retryAndRemoveAllFailed", "POST"); await loadData(); } } function renderFailureStack(index) { const focusedException = data.failed[index]; focusedException.renderedStack = ""; if (focusedException.backtrace) { focusedException.renderedStack = focusedException.backtrace.join("\r\n"); } data.focusedException = focusedException; data.showModal = true; setData({ ...data }); } function onHide() { data.showModal = false; setData({ ...data }); } let index = -1 + data.perPage * data.page; let argCounter = -1; return ( <Page client={client}> <h1>Failed Jobs ({data.counts.failed})</h1> <Row> <Col md={12}> <ButtonToolbar> <Button onClick={retryAllFailedJobs} size="sm" variant="warning"> Retry All </Button> &nbsp; <Button onClick={removeAllFailedJobs} size="sm" variant="danger"> Remove All </Button> </ButtonToolbar> </Col> <br /> <br /> </Row> <Row> <Col md={12}> <Table id="failureTable" striped bordered hover size="sm"> <thead> <tr> <th>&nbsp;</th> <th>Date</th> <th>Exception</th> <th>Queue</th> <th>Method</th> <th>Worker</th> <th>Arguments</th> <th>&nbsp;</th> <th>&nbsp;</th> </tr> </thead> <tbody> {data.failed.map((f) => { index++; return ( <tr key={`failure-${index}`}> <td>{index + 1}</td> <td>{f.failed_at}</td> <td> <a onClick={renderFailureStack.bind(null, index)}></a> &nbsp; <strong> {f.exception}: {f.error} </strong> </td> <td> <span className="text-success"> <Link to={`/queue/${f.queue}`}>{f.queue}</Link> </span> </td> <td>{f.payload.class}</td> <td>{f.worker}</td> <td> <ul> {f.payload.args.map((a) => { argCounter++; return ( <li key={`arg-${argCounter}`}> {JSON.stringify(a)} </li> ); })} </ul> </td> <td> <Button onClick={retryFailedJob.bind(null, index)} variant="warning" size="sm" > Retry </Button> </td> <td> <Button onClick={removeFailedJob.bind(null, index)} variant="danger" size="sm" > Remove </Button> </td> </tr> ); })} </tbody> </Table> <Pagination history={history} page={data.page} total={data.counts.failed} perPage={data.perPage} base="/failed" /> </Col> </Row> <Modal show={data.showModal} onHide={onHide} size="xl"> <Modal.Header> <h3> {data.focusedException.exception}: {data.focusedException.error} </h3> </Modal.Header> <Modal.Body> <p> <strong>Queue</strong>: {data.focusedException.queue}{" "} </p> <p> <strong>Worker</strong>: {data.focusedException.worker}{" "} </p> <p> <strong>Payload</strong>: </p> <pre> {data.focusedException.payload ? JSON.stringify(data.focusedException.payload.args) : null} </pre> <p> <strong>Stack</strong>: </p> <pre>{data.focusedException.renderedStack}</pre> </Modal.Body> <Modal.Footer> <Button size="sm" onClick={onHide}> Close </Button> </Modal.Footer> </Modal> </Page> ); } export default FailedPage;