package contract import ( "errors" "fmt" ) // ErrOwnerRequired — приём по HTTP дошёл до заведения задачи, а владельца ему не // назвали. Значение сентинельное: нести отказу нечего, а имя учётной записи в // него не кладётся никогда. var ErrOwnerRequired = errors.New("owner is required to accept a record") // ErrRecordUnreadable — присланную запись не удалось прочитать: источник // метаданных не разобрал её содержимое. Причина отказа — сама запись, а не сбой // сервиса, и код ответа обязан называть причину, а не место. // // Заводится sentinel'ом, а не остаётся голой ошибкой источника метаданных: // ветвь по умолчанию отдала бы `500`, и «файл негоден» читалось бы как «сломался // сервер». Своих данных отказу нести нечего — имя файла в него не кладётся // никогда. var ErrRecordUnreadable = errors.New("uploaded record cannot be read") // ErrRecordTooLarge — присланная запись длиннее потолка размера. Самый частый // отказ у человека на мобильной сети, и прежде он уходил телом ограничителя тела // — мимо единой формы отказа. var ErrRecordTooLarge = errors.New("uploaded record exceeds size limit") // ErrTextNotReady — текста запрошенного вида у записи ещё нет. Состояние, а не // отсутствие: запись есть и принадлежит спрашивающему, просто конвейер до этого // вида не дошёл. Отвечать на это тем же, чем отвечает чужая запись, нельзя — // человек увидел бы «не найдено» на своей записи, загруженной минуту назад. var ErrTextNotReady = errors.New("requested text view is not ready yet") // ErrBadRequest — во входе запроса негодное значение: неизвестный вид текста, // нечитаемый ключ страницы, отрицательный размер. Отличается от ErrRecordUnreadable // тем, что негодна **просьба**, а не присланная запись. var ErrBadRequest = errors.New("request input is not valid") // ErrUnauthorized — сессии нет вовсе. Первая строка таблицы отображения, и без // собственного признака она собиралась бы руками мимо единой точки: правка формы // тела не доехала бы до неё, и два места разошлись бы молча. var ErrUnauthorized = errors.New("session is required") // ErrNotFound — под корнем приложения такого адреса нет. Отличается от // JobNotFoundError тем, что не найдена **просьба**, а не запись: тело у ответа // то же, но повод другой, и смешивать их в одном признаке значило бы называть // отсутствующий адрес отсутствующей записью. var ErrNotFound = errors.New("address not found") type JobNotFoundError struct { State string Message string } func (e *JobNotFoundError) Error() string { return fmt.Sprintf("%s - %s", e.State, e.Message) } // LostAcquisitionError — захват задачи за время работы шага достался другому. // Шаг, получивший его, завершается без записи результата: иначе два воркера // пишут в одну запись по очереди, портя её результат, и счётчик отказов // сбрасывает тот, кто уже не владелец. type LostAcquisitionError struct { JobID string } func (e *LostAcquisitionError) Error() string { return fmt.Sprintf("%s: job acquisition lost", e.JobID) } type NoopJobError struct { State string } func (e *NoopJobError) Error() string { return fmt.Sprintf("%s: no op job occur", e.State) }