Skip to content

Refactor CRUD operations to use Arrow's Raise for error handling#88

Draft
nomisRev wants to merge 1 commit intosmyrgeorge:mainfrom
nomisRev:arrow-raise-context
Draft

Refactor CRUD operations to use Arrow's Raise for error handling#88
nomisRev wants to merge 1 commit intosmyrgeorge:mainfrom
nomisRev:arrow-raise-context

Conversation

@nomisRev
Copy link

Hey!

I saw Sqlx4k come by again on my timeline, and wanted to check up on the recent updates when I saw Arrow 😁 When I checked the code I saw there context parameters support, so I made a small PR to show what it would like lifting the error to the context.

This would require updating the codegen. I could give it a shot if you like this proposal.

@smyrgeorge
Copy link
Owner

smyrgeorge commented Jan 16, 2026

Hey @nomisRev
Thanks for this PR and thanks for your availability to make further changes to this project. I really appreciate it.
I think, the solution that you are proposing is totally correct (and probably the next logical step) but I would like to see the "ergonomics" (and how it integrates) in some examples (I'm kindly new to working with arrow+context-parameters).

Recently, I started developing a new library (or toolkit if you like, I'm trying to avoid the term framework here), the name is ktkit, that uses ktor, kotlinx.serialization, arrow, log4k and sqlx4k.
Some features of sqlx4k are developed to be compatible and to provide good ergonomics to this new library.

You can find the ktkit here:
https://github.com/smyrgeorge/ktkit

Take a look at this example:
https://github.com/smyrgeorge/ktkit/blob/bccf71646759f23c5d1597218e6d8ac804054437/example/src/commonMain/kotlin/io/github/smyrgeorge/ktkit/example/test/TestService.kt#L20

The error mapper toAppResult is located here:
https://github.com/smyrgeorge/ktkit/blob/bccf71646759f23c5d1597218e6d8ac804054437/ktkit-sqlx4k/src/commonMain/kotlin/io/github/smyrgeorge/ktkit/sqlx4k/DatabaseService.kt#L27

Now, with the current implementation I can easily map the error domain from sqlx4k (DbResult) to the app domain (AppResult) with just an extension method.

Also, in the example that I sent you, notice that the ExecContext has the following definition:

class ExecContext(
    val reqId: String,
    val reqTs: Instant = Clock.System.now(),
    val principal: Principal,
    ...
) : Raise<ErrorSpec>, TracingContext by tracing, CoroutineContext.Element {

Notice the Raise<ErrorSpec> here.

If we make the change that you are proposing how the code should be changed?

Edit:

In the example that I sent you I should probably change the function test to something like the following:

context(_: ExecContext, _: Transaction)
suspend fun test(): List<Test> {
    log.info { "Fetching all tests" }

    sqlx4k() // Compilation error

    return findAll().bind().also {
        log.info { "Fetched ${it.size} tests" }
    }
}

context(_: Raise<SQLError>)
fun sqlx4k(): Long = 5

In this case how can call the sqlx4k function?
I can do something like:

val a = either { test1() }.toAppResult().bind()

So the above example will be something like:

context(_: ExecContext, _: Transaction)
suspend fun test(): List<Test> {
    log.info { "Fetching all tests" }

    val a = either { test1() }.toAppResult().bind()

    return findAll().bind().also {
        log.info { "Fetched ${it.size} tests" }
    }
}

Is there any other way?

@smyrgeorge
Copy link
Owner

smyrgeorge commented Jan 18, 2026

Hello @nomisRev
I changed my example:
https://github.com/smyrgeorge/ktkit/blob/main/example/src/commonMain/kotlin/io/github/smyrgeorge/ktkit/example/test/TestService.kt

You're right, the way that you are proposing works way better, and I prefer way more the ergonomics this way.
I've had totally missed this concept, it's like doing error lifting in scala. Really cool 👍

So, if you're willing, go on and make the changes in the codegen module also 😄.

Thanks a lot

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants