I’m on page 416, when the flight flows are expanded from a single fetch to a list of fetches and emitting a countdown timer.
I ran into a problem where the fetchFlight function would report that it finished it’s loyalty fetch, but then hang on the flight fetch and exit the process due to timeout. I tracked down the problem to the import statements at the top of my FlightWatcher.kt file.
when my imports are
import kotlinx.coroutines.delay
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.flow
import kotlinx.coroutines.runBlocking
import kotlinx.coroutines.flow.collect
output is
getting the latest flight info
Start flight fetch
Start loyalty fetch
combine flight data
End loyalty fetch
Exception in thread "main" kotlinx.coroutines.TimeoutCancellationException: Timed out waiting for 15000 ms
at kotlinx.coroutines.TimeoutKt.TimeoutCancellationException(Timeout.kt:186)
at kotlinx.coroutines.TimeoutCoroutine.run(Timeout.kt:156)
at kotlinx.coroutines.EventLoopImplBase$DelayedRunnableTask.run(EventLoop.common.kt:497)
at kotlinx.coroutines.EventLoopImplBase.processNextEvent(EventLoop.common.kt:274)
at kotlinx.coroutines.DefaultExecutor.run(DefaultExecutor.kt:69)
at java.base/java.lang.Thread.run(Thread.java:1589)
Process finished with exit code 1
When my imports are:
import kotlinx.coroutines.delay
import kotlinx.coroutines.flow.*
import kotlinx.coroutines.runBlocking
output is correct:
getting the latest flight info
Start flight fetch
Start loyalty fetch
combine flight data
End loyalty fetch
End flight fetch
Start flight fetch
Start loyalty fetch
combine flight data
End loyalty fetch
End flight fetch
found flights for Madrigal (RI8102), Polarcubis (LM6344)
Madrigal: FlightStatus(flightNumber=RI8102, passengerName=Madrigal, passengerLoyaltyTier=Bronze, originAirport=MOY, destinationAirport=ENE, status=On Time, departureTimeInMinutes=52)
Madrigal: FlightStatus(flightNumber=RI8102, passengerName=Madrigal, passengerLoyaltyTier=Bronze, originAirport=MOY, destinationAirport=ENE, status=On Time, departureTimeInMinutes=51)
Madrigal: FlightStatus(flightNumber=RI8102, passengerName=Madrigal, passengerLoyaltyTier=Bronze, originAirport=MOY, destinationAirport=ENE, status=On Time, departureTimeInMinutes=50)
Madrigal: FlightStatus(flightNumber=RI8102, passengerName=Madrigal, passengerLoyaltyTier=Bronze, originAirport=MOY, destinationAirport=ENE, status=On Time, departureTimeInMinutes=49)
Madrigal: FlightStatus(flightNumber=RI8102, passengerName=Madrigal, passengerLoyaltyTier=Bronze, originAirport=MOY, destinationAirport=ENE, status=On Time, departureTimeInMinutes=48)
Finished tracking Madrigal's flight
Polarcubis: FlightStatus(flightNumber=LM6344, passengerName=Polarcubis, passengerLoyaltyTier=Platinum, originAirport=ACR, destinationAirport=DMF, status=On Time, departureTimeInMinutes=116)
Polarcubis: FlightStatus(flightNumber=LM6344, passengerName=Polarcubis, passengerLoyaltyTier=Platinum, originAirport=ACR, destinationAirport=DMF, status=On Time, departureTimeInMinutes=115)
Polarcubis: FlightStatus(flightNumber=LM6344, passengerName=Polarcubis, passengerLoyaltyTier=Platinum, originAirport=ACR, destinationAirport=DMF, status=On Time, departureTimeInMinutes=114)
Polarcubis: FlightStatus(flightNumber=LM6344, passengerName=Polarcubis, passengerLoyaltyTier=Platinum, originAirport=ACR, destinationAirport=DMF, status=On Time, departureTimeInMinutes=113)
Polarcubis: FlightStatus(flightNumber=LM6344, passengerName=Polarcubis, passengerLoyaltyTier=Platinum, originAirport=ACR, destinationAirport=DMF, status=On Time, departureTimeInMinutes=112)
Finished tracking Polarcubis's flight
Process finished with exit code 0
The current state of my FlightWatcher file is
import kotlinx.coroutines.delay
import kotlinx.coroutines.flow.*
import kotlinx.coroutines.runBlocking
fun main(){
runBlocking{
println("getting the latest flight info")
val flights = fetchFlights()
val flightDescriptions = flights.joinToString{
"${it.passengerName} (${it.flightNumber})"
}
println("found flights for $flightDescriptions")
flights.forEach{
watchFlight(it)
}
}
}
suspend fun watchFlight(initialFlight: FlightStatus){
val passengerName = initialFlight.passengerName
val currentFlight: Flow<FlightStatus> = flow {
var flight = initialFlight
repeat(5){
emit(flight)
delay(100)
flight = flight.copy(
departureTimeInMinutes = flight.departureTimeInMinutes -1
)
}
}
currentFlight.collect{println("$passengerName: $it")}
println("Finished tracking $passengerName's flight")
}
suspend fun fetchFlights(
passengerNames: List<String> = listOf("Madrigal", "Polarcubis")
) = passengerNames.map { fetchFlight(it)}
I’m curious as to which function is “breaking” when I am listing out a few individual kotlinx.coroutines.flow things instead of .flow.*, and I’m also not sure why it hangs in the flightFetch function, which is not only in a different file, but also gets the loyalty data but not flight data. Doesn’t make sense to me at first glance.