1
0
Fork 0

feat: better error messaging

This commit is contained in:
Sean Sube 2024-01-08 22:14:32 -06:00
parent 0215cb9ac6
commit 2eb90ba559
Signed by: ssube
GPG Key ID: 3EED7B957D362AF1
14 changed files with 44 additions and 14 deletions

View File

@ -65,7 +65,7 @@ class EditSafetyStage(BaseStage):
if is_csam: if is_csam:
logger.warning("blocking csam result") logger.warning("blocking csam result")
raise CancelledException("csam detected") raise CancelledException(reason="csam")
else: else:
return StageResult.from_images(results, metadata=sources.metadata) return StageResult.from_images(results, metadata=sources.metadata)
except ImportError: except ImportError:

View File

@ -174,7 +174,7 @@ class ChainPipeline:
worker.set_tiles(0) worker.set_tiles(0)
if must_tile: if must_tile:
logger.info( logger.info(
"image contains sources or is larger than tile size of %s, tiling stage", "image has mask or is larger than tile size of %s, tiling stage",
tile, tile,
) )

View File

@ -59,7 +59,9 @@ def add_safety_stage(
if server.has_feature("horde-safety"): if server.has_feature("horde-safety"):
from ..chain.edit_safety import EditSafetyStage from ..chain.edit_safety import EditSafetyStage
pipeline.stage(EditSafetyStage(), StageParams()) pipeline.stage(
EditSafetyStage(), StageParams(tile_size=EditSafetyStage.max_tile)
)
def run_txt2img_pipeline( def run_txt2img_pipeline(

View File

@ -1,3 +1,6 @@
from typing import Optional
class RetryException(Exception): class RetryException(Exception):
""" """
Used when a chain pipeline has run out of retries. Used when a chain pipeline has run out of retries.
@ -11,7 +14,12 @@ class CancelledException(Exception):
Used when a job has been cancelled and needs to stop. Used when a job has been cancelled and needs to stop.
""" """
pass reason: Optional[str]
def __init__(self, *args: object, reason: Optional[str] = None) -> None:
super().__init__(*args)
self.reason = reason
class RequestException(Exception): class RequestException(Exception):

View File

@ -1,7 +1,7 @@
from io import BytesIO from io import BytesIO
from logging import getLogger from logging import getLogger
from os import path from os import path
from typing import Any, Dict, List from typing import Any, Dict, List, Optional
from flask import Flask, jsonify, make_response, request, url_for from flask import Flask, jsonify, make_response, request, url_for
from jsonschema import validate from jsonschema import validate
@ -117,8 +117,9 @@ def image_reply(
stages: Progress = None, stages: Progress = None,
steps: Progress = None, steps: Progress = None,
tiles: Progress = None, tiles: Progress = None,
outputs: List[str] = None, outputs: Optional[List[str]] = None,
metadata: List[ImageMetadata] = None, metadata: Optional[List[ImageMetadata]] = None,
reason: Optional[str] = None,
) -> Dict[str, Any]: ) -> Dict[str, Any]:
if queue is None: if queue is None:
queue = EMPTY_PROGRESS queue = EMPTY_PROGRESS
@ -141,6 +142,9 @@ def image_reply(
"tiles": tiles.tojson(), "tiles": tiles.tojson(),
} }
if reason is not None:
data["reason"] = reason
if outputs is not None: if outputs is not None:
if metadata is None: if metadata is None:
logger.error("metadata is required with outputs") logger.error("metadata is required with outputs")
@ -705,6 +709,7 @@ def job_status(server: ServerContext, pool: DevicePoolExecutor):
tiles=progress.tiles, tiles=progress.tiles,
outputs=outputs, outputs=outputs,
metadata=metadata, metadata=metadata,
reason=progress.reason,
) )
) )
else: else:

View File

@ -1,5 +1,5 @@
from enum import Enum from enum import Enum
from typing import Any, Callable, Dict from typing import Any, Callable, Dict, Optional
class JobStatus(str, Enum): class JobStatus(str, Enum):
@ -64,7 +64,8 @@ class ProgressCommand:
job: str job: str
job_type: str job_type: str
status: JobStatus status: JobStatus
result: Any # really StageResult but that would be a very circular import reason: Optional[str]
result: Optional[Any] # really StageResult but that would be a very circular import
steps: Progress steps: Progress
stages: Progress stages: Progress
tiles: Progress tiles: Progress
@ -79,6 +80,7 @@ class ProgressCommand:
stages: Progress, stages: Progress,
tiles: Progress, tiles: Progress,
result: Any = None, result: Any = None,
reason: Optional[str] = None,
): ):
self.job = job self.job = job
self.job_type = job_type self.job_type = job_type
@ -90,6 +92,7 @@ class ProgressCommand:
self.stages = stages self.stages = stages
self.tiles = tiles self.tiles = tiles
self.result = result self.result = result
self.reason = reason
class JobCommand: class JobCommand:

View File

@ -218,7 +218,7 @@ class WorkerContext:
block=False, block=False,
) )
def fail(self) -> None: def fail(self, reason: Optional[str] = None) -> None:
if self.job is None: if self.job is None:
logger.warning("setting failure without an active job") logger.warning("setting failure without an active job")
else: else:
@ -232,6 +232,7 @@ class WorkerContext:
steps=self.steps, steps=self.steps,
stages=self.stages, stages=self.stages,
tiles=self.tiles, tiles=self.tiles,
reason=reason,
# TODO: should this include partial results? # TODO: should this include partial results?
) )
self.progress.put( self.progress.put(

View File

@ -5,7 +5,7 @@ from sys import exit
from setproctitle import setproctitle from setproctitle import setproctitle
from ..errors import RetryException from ..errors import CancelledException, RetryException
from ..server import ServerContext, apply_patches from ..server import ServerContext, apply_patches
from ..torch_before_ort import get_available_providers from ..torch_before_ort import get_available_providers
from .context import WorkerContext from .context import WorkerContext
@ -82,13 +82,16 @@ def worker_main(
logger.exception("value error in worker, exiting") logger.exception("value error in worker, exiting")
worker.fail() worker.fail()
return exit(EXIT_ERROR) return exit(EXIT_ERROR)
except CancelledException as e:
logger.warning("job was cancelled, continuing")
worker.fail(e.reason or "cancelled")
except Exception as e: except Exception as e:
e_str = str(e) e_str = str(e)
# restart the worker on memory errors # restart the worker on memory errors
for e_mem in MEMORY_ERRORS: for e_mem in MEMORY_ERRORS:
if e_mem in e_str: if e_mem in e_str:
logger.error("detected out-of-memory error, exiting: %s", e) logger.error("detected out-of-memory error, exiting: %s", e)
worker.fail() worker.fail("oom")
return exit(EXIT_MEMORY) return exit(EXIT_MEMORY)
# carry on for other errors # carry on for other errors

View File

@ -89,7 +89,7 @@ export const UNKNOWN_ERROR = `${IMAGE_ERROR}unknown`;
export function getImageErrorReason(image: FailedJobResponse | UnknownJobResponse) { export function getImageErrorReason(image: FailedJobResponse | UnknownJobResponse) {
if (image.status === JobStatus.FAILED) { if (image.status === JobStatus.FAILED) {
const error = image.error; const error = image.reason;
if (doesExist(error) && error.startsWith(ANY_ERROR)) { if (doesExist(error) && error.startsWith(ANY_ERROR)) {
return error; return error;
} }

View File

@ -13,7 +13,9 @@ export const I18N_STRINGS_DE = {
convert: '', convert: '',
error: { error: {
image: { image: {
csam: '',
memory: '', memory: '',
oom: '',
unknown: '', unknown: '',
}, },
inpaint: { inpaint: {

View File

@ -8,7 +8,9 @@ export const I18N_STRINGS_EN = {
convert: 'Save and Convert', convert: 'Save and Convert',
error: { error: {
image: { image: {
csam: 'CSAM detected',
memory: 'Memory error generating image', memory: 'Memory error generating image',
oom: 'Out of memory generating image',
unknown: 'Unknown error generating image', unknown: 'Unknown error generating image',
}, },
inpaint: { inpaint: {

View File

@ -13,7 +13,9 @@ export const I18N_STRINGS_ES = {
convert: '', convert: '',
error: { error: {
image: { image: {
csam: '',
memory: '', memory: '',
oom: '',
unknown: '', unknown: '',
}, },
inpaint: { inpaint: {

View File

@ -13,7 +13,9 @@ export const I18N_STRINGS_FR = {
convert: '', convert: '',
error: { error: {
image: { image: {
csam: '',
memory: '', memory: '',
oom: '',
unknown: '', unknown: '',
}, },
inpaint: { inpaint: {

View File

@ -76,7 +76,7 @@ export interface CancelledJobResponse extends BaseJobResponse {
export interface FailedJobResponse extends BaseJobResponse { export interface FailedJobResponse extends BaseJobResponse {
status: JobStatus.FAILED; status: JobStatus.FAILED;
error?: string; reason?: string;
} }
/** /**