-
Notifications
You must be signed in to change notification settings - Fork 10
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
fix(model-server): do not execute long-running repository operation on request threads #563
Conversation
model-server/src/main/kotlin/org/modelix/model/server/handlers/KeyValueLikeModelServer.kt
Fixed
Show fixed
Hide fixed
de7240f
to
85297b9
Compare
model-server/src/main/kotlin/org/modelix/model/server/handlers/KeyValueLikeModelServer.kt
Outdated
Show resolved
Hide resolved
85297b9
to
7cb2221
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The problematic cases are where a thread is blocked and not doing anything. If there are a lot of request that are blocked at the same location we need a lot of threads.
Using withContext(Dispatchers.IO)
is not the best solution, because it just uses the unconstrained thread pool, but this still creates a lot of unnecessary threads. A better solution is to replace the blocking calls by coroutine features.
From the changes in this PR I identified the following problematic calls:
The transactions.txStart()
call in IgniteStoreClient.runTransaction
.
We can wrap that code with a Mutex to avoid trying to start a transaction while there is already an active one. This suspends the coroutine instead of blocking the thread.
The usage of lazy
in RepositoriesManager.computeDelta
.
This can be replaced by a Deferred
data type and an async
call.
Both changes will force you to make the methods, and all the transitive usages, suspendable. This automatically fixes all the locations where you now added withContext(Dispatchers.IO)
, which is then not required anymore.
I guess this also answers the question
On which level do we want to decide about execution (e.g. which thread pool to execute computation on)
We avoid blocking calls by using coroutine features. If not possible, we use withContext(Dispatchers.IO)
around that call. The propagated suspend
keyword automatically ensures that all HTTP endpoints are fixed.
7cb2221
to
f2f6c1b
Compare
@@ -283,71 +284,71 @@ | |||
return result | |||
} | |||
|
|||
protected fun CallContext.putEntries(newEntries: Map<String, String?>) { | |||
protected suspend fun CallContext.putEntries(newEntries: Map<String, String?>) { |
Check warning
Code scanning / detekt
Prefer splitting up complex methods into smaller, easier to test methods. Warning
@@ -283,71 +284,71 @@ | |||
return result | |||
} | |||
|
|||
protected fun CallContext.putEntries(newEntries: Map<String, String?>) { | |||
protected suspend fun CallContext.putEntries(newEntries: Map<String, String?>) { |
Check warning
Code scanning / detekt
Excessive nesting leads to hidden complexity. Prefer extracting code to make it easier to understand. Warning
model-server/src/main/kotlin/org/modelix/model/server/handlers/RepositoriesManager.kt
Fixed
Show fixed
Hide fixed
model-server/src/main/kotlin/org/modelix/model/server/handlers/RepositoriesManager.kt
Outdated
Show resolved
Hide resolved
Execute non suspendable part outside request threads.
50c3e8a
to
9751444
Compare
private val LOG = LoggerFactory.getLogger(VersionDeltaCache::class.java) | ||
} | ||
|
||
private val cacheMap = LRUMap<Pair<String, String?>, SoftReference<Deferred<ObjectDataMap>>>(10) |
Check warning
Code scanning / detekt
This expression contains a magic number. Consider defining it to a well named constant. Warning
model-server/src/main/kotlin/org/modelix/model/server/handlers/RepositoriesManager.kt
Outdated
Show resolved
Hide resolved
model-server/src/main/kotlin/org/modelix/model/server/handlers/RepositoriesManager.kt
Show resolved
Hide resolved
…pendable transactions This avoids blocking one additional thread.
9751444
to
79af748
Compare
🎉 This PR is included in version 5.1.1 🎉 The release is available on GitHub release Your semantic-release bot 📦🚀 |
Execute them on Dispatchers.IO because they are mostly blocked by waiting for data from store. Long-running operations are
computeDelta
andmergeChanges
.