in core/invoker/src/main/scala/org/apache/openwhisk/core/containerpool/v2/FunctionPullingContainerPool.scala [448:513]
private def adjustPrewarmedContainer(init: Boolean, scheduled: Boolean): Unit = {
if (!shuttingDown) {
if (scheduled) {
//on scheduled time, remove expired prewarms
ContainerPoolV2.removeExpired(poolConfig, prewarmConfig, prewarmedPool).foreach { p =>
prewarmedPool = prewarmedPool - p
p ! Remove
}
//on scheduled time, emit cold start counter metric with memory + kind
coldStartCount foreach { coldStart =>
val coldStartKey = coldStart._1
MetricEmitter.emitCounterMetric(
LoggingMarkers.CONTAINER_POOL_PREWARM_COLDSTART(coldStartKey.memory.toString, coldStartKey.kind))
}
}
ContainerPoolV2
.increasePrewarms(
init,
scheduled,
coldStartCount,
prewarmConfig,
prewarmedPool,
prewarmStartingPool,
prewarmConfigQueue)
.foreach { c =>
val config = c._1
val currentCount = c._2._1
val desiredCount = c._2._2
if (prewarmCreateFailedCount.get() > poolConfig.prewarmMaxRetryLimit) {
logging.warn(
this,
s"[kind: ${config.exec.kind}, memory: ${config.memoryLimit.toString}] prewarm create failed count exceeds max retry limit: ${poolConfig.prewarmMaxRetryLimit}, currentCount: ${currentCount}, desiredCount: ${desiredCount}")
} else {
if (currentCount < desiredCount) {
(currentCount until desiredCount).foreach { _ =>
poolConfig.prewarmContainerCreationConfig match {
case Some(_) =>
prewarmConfigQueue =
prewarmConfigQueue.enqueue((config.exec, config.memoryLimit, config.reactive.map(_.ttl)))
case None =>
prewarmContainer(config.exec, config.memoryLimit, config.reactive.map(_.ttl))
}
}
}
}
}
// run queue consumer
poolConfig.prewarmContainerCreationConfig.foreach(config => {
logging.info(
this,
s"prewarm container creation is starting with creation delay configuration [maxConcurrent: ${config.maxConcurrent}, creationDelay: ${config.creationDelay.toMillis} millisecond]")
if (preWarmScheduler.isEmpty) {
preWarmScheduler = Some(
context.system.scheduler
.scheduleAtFixedRate(0.seconds, config.creationDelay, self, PrewarmContainer(config.maxConcurrent)))
}
})
if (scheduled) {
// lastly, clear coldStartCounts each time scheduled event is processed to reset counts
coldStartCount = immutable.Map.empty[ColdStartKey, Int]
}
}
}