Skip to content

Commit c2f5d67

Browse files
jiangpengchengJesseStutler
authored andcommitted
Take revision into consideration when choose warm container (apache#5233)
1 parent b571164 commit c2f5d67

File tree

2 files changed

+61
-2
lines changed

2 files changed

+61
-2
lines changed

core/scheduler/src/main/scala/org/apache/openwhisk/core/scheduler/container/ContainerManager.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -251,7 +251,7 @@ class ContainerManager(jobManagerFactory: ActorRefFactory => ActorRef,
251251
// Filter out messages which can use warmed container
252252
private def filterWarmedCreations(msgs: List[ContainerCreationMessage]) = {
253253
msgs.filter { msg =>
254-
val warmedPrefix = containerPrefix(ContainerKeys.warmedPrefix, msg.invocationNamespace, msg.action)
254+
val warmedPrefix = containerPrefix(ContainerKeys.warmedPrefix, msg.invocationNamespace, msg.action, Some(msg.revision))
255255
val chosenInvoker = warmedContainers
256256
.filter(!inProgressWarmedContainers.values.toSeq.contains(_))
257257
.find { container =>

tests/src/test/scala/org/apache/openwhisk/core/scheduler/container/test/ContainerManagerTests.scala

Lines changed: 60 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -278,7 +278,7 @@ class ContainerManagerTests
278278
)
279279
expectGetInvokers(mockEtcd, invokers)
280280
expectGetInvokers(mockEtcd, invokers)
281-
expectGetInvokers(mockEtcd, invokers) // this test case will run `getPrefix` twice
281+
expectGetInvokers(mockEtcd, invokers) // this test case will run `getPrefix` twice, and another one for warmup
282282

283283
val mockJobManager = TestProbe()
284284
val mockWatcher = TestProbe()
@@ -377,6 +377,65 @@ class ContainerManagerTests
377377
receiver.expectMsg(s"invoker0-$msg1")
378378
}
379379

380+
it should "not try warmed containers if revision is unmatched" in {
381+
val mockEtcd = mock[EtcdClient]
382+
383+
// for test, only invoker2 is healthy, so that no-warmed creations can be only sent to invoker2
384+
val invokers: List[InvokerHealth] = List(
385+
InvokerHealth(InvokerInstanceId(0, userMemory = testMemory, tags = Seq.empty[String]), Unhealthy),
386+
InvokerHealth(InvokerInstanceId(1, userMemory = testMemory, tags = Seq.empty[String]), Unhealthy),
387+
InvokerHealth(InvokerInstanceId(2, userMemory = testMemory, tags = Seq.empty[String]), Healthy),
388+
)
389+
expectGetInvokers(mockEtcd, invokers)
390+
expectGetInvokers(mockEtcd, invokers) // one for warmup
391+
392+
val mockJobManager = TestProbe()
393+
val mockWatcher = TestProbe()
394+
val receiver = TestProbe()
395+
396+
val manager =
397+
system.actorOf(ContainerManager
398+
.props(factory(mockJobManager), mockMessaging(Some(receiver.ref)), testsid, mockEtcd, config, mockWatcher.ref))
399+
400+
// there are 1 warmed container for `test-namespace/test-action` but with a different revision
401+
manager ! WatchEndpointInserted(
402+
ContainerKeys.warmedPrefix,
403+
ContainerKeys.warmedContainers(
404+
testInvocationNamespace,
405+
testfqn,
406+
DocRevision("2-testRev"),
407+
InvokerInstanceId(0, userMemory = 0.bytes),
408+
ContainerId("fake")),
409+
"",
410+
true)
411+
412+
val msg =
413+
ContainerCreationMessage(
414+
TransactionId.testing,
415+
testInvocationNamespace,
416+
testfqn,
417+
testRevision,
418+
actionMetadata,
419+
testsid,
420+
schedulerHost,
421+
rpcPort)
422+
423+
// it should not reuse the warmed container
424+
manager ! ContainerCreation(List(msg), 128.MB, testInvocationNamespace)
425+
426+
// ignore warmUp message
427+
receiver.ignoreMsg {
428+
case s: String => s.contains("warmUp")
429+
}
430+
431+
// it should be scheduled to the sole health invoker: invoker2
432+
receiver.expectMsg(s"invoker2-$msg")
433+
434+
mockJobManager.expectMsgPF() {
435+
case RegisterCreationJob(`msg`) => true
436+
}
437+
}
438+
380439
it should "rescheduling container creation" in {
381440
val mockEtcd = mock[EtcdClient]
382441
(mockEtcd

0 commit comments

Comments
 (0)