|
| 1 | +package gent.zeus.guitar |
| 2 | + |
| 3 | +/** |
| 4 | + * error generated by the application that can be returned to the user |
| 5 | + * |
| 6 | + * @param message message of the error |
| 7 | + * @param remoteError error from the remote that caused this error |
| 8 | + */ |
| 9 | +abstract class DataFetchError(val message: String, val remoteError: String?, val httpStatusCode: Int) { |
| 10 | + |
| 11 | + override fun toString(): String { |
| 12 | + return this::class.simpleName ?: "anonymous class" |
| 13 | + } |
| 14 | +} |
| 15 | + |
| 16 | +/** |
| 17 | + * error caused by user wrongdoing |
| 18 | + */ |
| 19 | +open class UserError(message: String, remoteError: String?, httpStatusCode: Int = 400) : |
| 20 | + DataFetchError(message, remoteError, httpStatusCode) |
| 21 | + |
| 22 | +/** |
| 23 | + * error caused by server mishaps |
| 24 | + */ |
| 25 | +open class ServerError(message: String, remoteError: String?, httpStatusCode: Int = 500) : |
| 26 | + DataFetchError(message, remoteError, httpStatusCode) |
| 27 | + |
| 28 | +class MultiError(errors: List<DataFetchError>) : DataFetchError( |
| 29 | + message = errors.joinToString( |
| 30 | + ", ", |
| 31 | + if (errors.size > 1) "multiple errors were encountered: " else "", |
| 32 | + ) { "${it.message} (${it.httpStatusCode})" }, |
| 33 | + remoteError = errors.joinToString( |
| 34 | + "; ", |
| 35 | + ) { "${it.remoteError}" }, |
| 36 | + httpStatusCode = when { |
| 37 | + errors.any { it is UserError && it.httpStatusCode == 404 } -> 404 |
| 38 | + errors.any { it is UserError } -> 400 |
| 39 | + else -> 500 |
| 40 | + } |
| 41 | +) |
| 42 | + |
| 43 | +/** |
| 44 | + * success or error when handling musical data |
| 45 | + */ |
| 46 | +sealed class DataResult<out T> { |
| 47 | + data class Ok<T>(val value: T) : DataResult<T>() |
| 48 | + data class Error<E : DataFetchError>(val error: E) : DataResult<Nothing>() |
| 49 | +} |
| 50 | + |
| 51 | +/** |
| 52 | + * log all the errors in the list |
| 53 | + * @param pre: bit to put before the error message |
| 54 | + */ |
| 55 | +fun <E : DataFetchError> Iterable<E>.logErrors(pre: String) = onEach { |
| 56 | + logger.error("$pre ${it.message} (${it.httpStatusCode})") |
| 57 | +} |
| 58 | + |
| 59 | +/** |
| 60 | + * tries to execute the code block. if the code throws an exception, it makes an error log statement |
| 61 | + * and re-throws the exception |
| 62 | + * |
| 63 | + * @param messageOnFail message to put in log statement (will append ` (stacktrace below)`) |
| 64 | + * @param block code block to try executing |
| 65 | + */ |
| 66 | +inline fun logExceptionFail(messageOnFail: String, block: () -> Unit) { |
| 67 | + try { |
| 68 | + block() |
| 69 | + } catch (e: Exception) { |
| 70 | + logger.error("$messageOnFail: ${e.message} (stacktrace below)") |
| 71 | + throw e |
| 72 | + } |
| 73 | +} |
| 74 | + |
| 75 | +inline fun <R> logExceptionWarn(messageOnFail: String, block: () -> R) = |
| 76 | + try { |
| 77 | + block() |
| 78 | + } catch (e: Exception) { |
| 79 | + logger.warn("$messageOnFail: ${e.message} (stacktrace below)") |
| 80 | + e.printStackTrace() |
| 81 | + null |
| 82 | + } |
| 83 | + |
0 commit comments