Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Feature Request] Kotlin Non-Blocking #771

Open
thalesdev opened this issue Nov 11, 2024 · 6 comments
Open

[Feature Request] Kotlin Non-Blocking #771

thalesdev opened this issue Nov 11, 2024 · 6 comments
Labels
pending Postpone plans because of more important tasks

Comments

@thalesdev
Copy link

Is there any chance of adding non-blocking features? In the development of idiomatic applications in Kotlin, the use of coroutines is essential. It would be very interesting to have a data layer with the non-blocking jimmer. With an API similar to that of Micronaut Data R2DBC

@JeanPoffo
Copy link

It would really be an excellent feature!

@babyfish-ct
Copy link
Owner

This is a huge feature request, which will not be considered before 1.0. Because save-command is very complicated, and its internal mechanism is too complicated. It took a year to make up my mind to refactor it, and the refactoring took 3 months.

The currently save command of the document is old and is being refactored, only the save-command related project in the attached examples is the latest demonstration

In addition, I also want to use the time when Jimmer evolves to 1.0 to observe whether the newer JDK can sufficiently optimize the virtual thread that currently performs poorly.

@babyfish-ct babyfish-ct added the pending Postpone plans because of more important tasks label Nov 11, 2024
@ForteScarlet
Copy link
Contributor

I guess wrapping up the sqlClient operations with withContext is an option to consider.

withContext(Dispatchers.VirtualOrIO) {
    sql.executeQuery(...)
}

Instead of making wholesale changes to the API or copying an asynchronous API with almost the same amount of work, I think it's better to look forward to virtual threads, if only for the sake of better resource utilization for IO behavior.

Even though virtual threads aren't performing as well as we might expect, at least it's still trying, isn't it?

As far as I know, PostgreSQL, H2 and MySQL(9.x) should already have optimisations or changes for virtual thread.

@SWQXDBA
Copy link
Contributor

SWQXDBA commented Nov 20, 2024

I think R2DBC will fade away as virtual threads mature.
Locking due to the synchronized keyword is also addressed in jdk24.
As time goes on, there is less and less reason to use R2DBC.

@JeanPoffo
Copy link

@ForteScarlet is not that simple. Mannualy using different contexts, the thread is changed arbitrarily and the common mechanisms of transaction does not support this case. For this motive, native async mechanisms (R2DBC) are the best approach.

@ForteScarlet
Copy link
Contributor

ForteScarlet commented Nov 22, 2024

@JeanPoffo It's true that switching contexts does cause threads to be more alive and kicking. But with Jimmer, it has no state, doesn't care about transactions, and can also provide specific connections in almost any API.

Transactions that can fail due to thread switches are usually caused by the same thing as annotated transactions(e.g. spring's @Transactional ) or ThreadLocal connections.

I think there are many ways to compromise, such as starting a transaction in the context.

withContext(Dispatchers.xxx) {
    transactionManager.execute {
        sql.createQuery(...) {...}
    }
}

Or manually control your connection and transaction.

val dataSource: DataSource = ...
val newConnection = getConnection(dataSource)

try {
    withContext(Dispatcher1) {
        sql.createQuery(...) { ... }.execute(newConnection)
    }
          
    withContext(Dispatcher2) {
        sql.entities.save(..., con = newConnection) {
            // Save command DSL...
        }
    }
            
    // commit when success.
    newConnection.commit()
} catch (error: Throwable) {
    // Rollback when error
    newConnection.rollback()
}

releaseConnection(newConnection)

In Kotlin, ThreadLocal can also work together with context, for example, using ThreadLocal.asContextElement() (This may be useful if you plan to customise the ConnectionManager ).

In Exposed, they also provide a solution to turn on transactions using a suspend function, although they are also JDBC-based.

Of course, all this is not to deny R2DBC; if it can truly fully support R2DBC, that would definitely be a wonderful thing!

However, as mentioned by @SWQXDBA, with the gradual maturation of virtual threads, the boundary between reactive programming and virtual threads in the JVM will become increasingly blurred.

For Kotlin, it might be okay, but for Java, both writing and debugging with reactive APIs is not a very good experience.

Regardless, the above is just my personal opinion.
I am also very much looking forward to the day when Jimmer can support R2DBC!
Perhaps in the future, there will be even more excellent solutions for Java database connectivity 😄

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
pending Postpone plans because of more important tasks
Projects
None yet
Development

No branches or pull requests

5 participants