Skip to content

Instantly share code, notes, and snippets.

View supermanue's full-sized avatar

Manuel Rodríguez Pascual supermanue

View GitHub Profile
@supermanue
supermanue / ErrorHandling.scala
Created March 20, 2022 15:55
Better error handling
#BEFORE
def get(id: Int): Task[User] =
SQL
.get(id)
.option
.transact(tnx)
.foldM(
err => Task.fail(err),
maybeUser => Task.require(UserNotFound(id))(Task.succeed(maybeUser))
)
trait AppError {
val message: String
}
final case class DBError(error: String) extends AppError {
val message = s"DBError: $error"
}
final case class UserNotFound(id: Int) extends AppError {
val message = s"User with id $id not found"
sealed trait BusinessLogicError {val msg: String}
case class NonExistingSchema(name: String, namespace: String) extends BusinessLogicError {
override val msg: String = s"schema with name $name and namespace $namespace does not exist"
}
case class StorageError(schema: Schema) extends BusinessLogicError {
override val msg: String = s"schema ${schema.toString} could not be stored for whatever reason"
}
def updateVersion(input: UserInput): Either[String, UserInput] =
for {
name <- refineV[NameRestrictions](input.name)
namespace <- refineV[NamespaceRestrictions](input.namespace)
version = getLatestVersion(name, namespace)
updatedVersion <- refineV[VersionRestrictions](version.value +1)
result = store(Schema(name, namespace, version))
} yield (UserInput(schema.name.value, schema.namespace.value))
case class UserInput(name: String, namespace: String)
def updateVersion(input: UserInput): UserInput = {
val lastVersion: Int = getLatestVersion(name, namespace)
val schemaToStore: Schema = InputToSchemaIso.get((userInput, lastVersion + 1))
val result: Schema = store(schemaToStore)
return InputToSchemaIso.reverseGet(result)
}
type NameRestrictions = MatchesRegex[W.`"[a-zA-Z]+[a-zA-Z0-9]*(?:[_-][a-zA-Z0-9]+)*"`.T]
type NamespaceRestrictions = MatchesRegex[W.`"[a-zA-Z]+[a-zA-Z0-9]*(?:[._-][a-zA-Z0-9]+)*"`.T]