After some refactoring we suddenly see this happening at runtime:
java.lang.StackOverflowError: null
at scala.collection.MapLike$MappedValues.get(MapLike.scala:249)
at scala.collection.MapLike$MappedValues.get(MapLike.scala:249)
at scala.collection.MapLike$MappedValues.get(MapLike.scala:249)
at scala.collection.MapLike$MappedValues.get(MapLike.scala:249)
at scala.collection.MapLike$MappedValues.get(MapLike.scala:249)
We found similar issues but none of them had exactly this trace:
The mentioned issues point to the lazyness of MapLike.mapValues
and after some further research we found the cause.
We have some cleanup code that is periodically called and does something like this:
case class EvictableValue(value: String, evictionTime: Instant)
val startData = Map(
"node1" -> Map(
"test" -> EvictableValue("bar", Instant.now().plusSeconds(1000))
)
)
// every n seconds we do the below code
// here simulated by the fold
val newData = (1 to 20000).foldLeft(startData){(data, _) =>
data.mapValues { value =>
value.filter(_._2.evictionTime.isBefore(Instant.now()))
}
}
// this stack overflows
val result = newData.get("test")
the solution was to switch to Map.transform
data.transform { (_, value) =>
value.filter(_._2.evictionTime.isBefore(Instant.now()))
}
or to force the view as explained here
data.mapValues{ value =>
value.filter(_._2.evictionTime.isBefore(Instant.now()))
}.view.force