https://kotlinlang.org logo
#getting-started
Title
# getting-started
b

Billy Newman

10/24/2023, 7:28 PM
Hello all, I am having a difficult time wrapping my head around a concurrency issue when using coroutines. As a small example I have data coming in from the system that I save locally to a database. At some frequency I want to push those results in a batch request to a server. I would like to ensure that only one push “task” is running at time to reduce load on the server. Will throw some code in this thread…
Copy code
private var pushJob: Job?  = null

fun onEvent(event: Event) {
   // Called on Main thread
   lifecycleScope.launch {
      eventRepository.save()  // Executes on IO thread
      pushJob?.join()
      pushJob = push(location)
   }
}

private suspend fun push() = coroutineScope {
   launch {
      Log.v("Test", "start push")
      ...
      locationRepository.pushLocations()  // Executes on IO thread
      ...
      Log.v("Test", "end push")
   }
}
Attempt a single push function executing at any given time. However I am not seeing start/stop pairs in the logs. Issue with the join and assignment not being synchronized?
e

ephemient

10/24/2023, 7:39 PM
coroutineScope { launch { ... } }
is basically equivalent to
...
, the job is always complete by the time the
suspend fun
returns
1
b

Billy Newman

10/24/2023, 9:28 PM
Ok, that makes sense, thank you. So something like this?
Copy code
fun onEvent(event: Event) {
   // Called on Main thread
   lifecycleScope.launch {
      eventRepository.save()  // Executes on IO thread
      pushJob?.join()
      pushJob = launch {
         Log.v("Test", "start push")
          ...
          locationRepository.pushLocations()  // Executes on IO thread
          ...
          Log.v("Test", "end push")
      }
   }
}
e

ephemient

10/24/2023, 9:29 PM
that could work but why not just use a
Mutex
?
👍 1
or a
limitedParallelism
dispatcher, if what you're running is a blocking operation
b

Billy Newman

10/24/2023, 9:35 PM
I would like to allow the save to be non blocking, but yeah I think this would achieve what I am after as the save is inside the coroutine and new calls to onEvent would just launch a new coroutine, save and then block if necessary
Copy code
fun onEvent(event: Event) {
   // Called on Main thread
   lifecycleScope.launch {
      eventRepository.save()  // Executes on IO thread
      mutex.withLock {
         Log.v("Test", "start push")
          ...
          locationRepository.pushLocations()  // Executes on IO thread
          ...
          Log.v("Test", "end push")
      }
   }
}