[
https://issues.apache.org/jira/browse/BROOKLYN-564?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=16251298#comment-16251298
]
Aled Sage commented on BROOKLYN-564:
------------------------------------
This is mainly just an issue with how the test is written, but could be an
issue for real users if they invoke the effector manually. The particularly bad
news if invoking it manually is that there is no mutex to stop the policy
trying to do something at the same time, so you can end up with promote/demote
effectors being called concurrently, which could lead to really bad behaviour!
If it's just the policy executing stuff, then it should be ok because the
policy is conceptually single-threaded (except where we invoke it explicitly in
setEntity, but if the policy exists from the beginning then it should happen
before the entity is managed and thus before any subscriptions kick-in).
> ElectPrimaryTest.testSelectionModeFailoverReelectWithPreference fails
> non-deterministically
> -------------------------------------------------------------------------------------------
>
> Key: BROOKLYN-564
> URL: https://issues.apache.org/jira/browse/BROOKLYN-564
> Project: Brooklyn
> Issue Type: Bug
> Reporter: Aled Sage
> Priority: Minor
>
> In Brooklyn 1.0.0-SNAPSHOT,
> {{ElectPrimaryTest.testSelectionModeFailoverReelectWithPreference fails
> non-deterministically}} sometimes fails in jenkins:
> {noformat}
> 2017-11-13 11:45:06,214 INFO TESTNG INVOKING CONFIGURATION: "Surefire test"
> - @BeforeMethod
> org.apache.brooklyn.camp.brooklyn.AbstractYamlRebindTest.setUp()
> 2017-11-13 11:45:06,214 INFO Added external config supplier named
> 'brooklyn-demo-sample':
> org.apache.brooklyn.core.config.external.InPlaceExternalConfigSupplier@380e4e8a
> 2017-11-13 11:45:06,219 INFO Rebind check: no existing state; will persist
> new items to /tmp/ElectPrimaryTest-UgLc
> 2017-11-13 11:45:06,220 INFO No Camp-YAML parser registered for parsing
> catalog item DSL; skipping DSL-parsing
> 2017-11-13 11:45:06,226 INFO Test class
> org.apache.brooklyn.camp.brooklyn.test.policy.failover.ElectPrimaryTest
> persisting to /tmp/ElectPrimaryTest-UgLc
> 2017-11-13 11:45:06,227 INFO TESTNG PASSED CONFIGURATION: "Surefire test" -
> @BeforeMethod
> org.apache.brooklyn.camp.brooklyn.AbstractYamlRebindTest.setUp() finished in
> 13 ms
> 2017-11-13 11:45:06,227 INFO TESTNG INVOKING: "Surefire test" -
> org.apache.brooklyn.camp.brooklyn.test.policy.failover.ElectPrimaryTest.testSelectionModeFailoverReelectWithPreference()
> 2017-11-13 11:45:06,279 INFO Test created app, and will now start
> BasicApplicationImpl{id=nq3a3nshq1}
> 2017-11-13 11:45:06,307 INFO Detected new primary
> TestEntityImpl{id=rg0witaqno} at BasicApplicationImpl{id=nq3a3nshq1}
> (previously had null)
> 2017-11-13 11:45:06,315 INFO Primary TestEntityImpl{id=rg0witaqno} at
> BasicApplicationImpl{id=nq3a3nshq1} detected as healthy
> 2017-11-13 11:45:06,329 INFO Started application
> BasicApplicationImpl{id=nq3a3nshq1}
> 2017-11-13 11:45:06,330 INFO Detected new primary
> TestEntityImpl{id=cijb9r79z1} at BasicApplicationImpl{id=nq3a3nshq1}
> (previously had TestEntityImpl{id=rg0witaqno})
> 2017-11-13 11:45:06,331 INFO Detected new primary
> TestEntityImpl{id=rg0witaqno} at BasicApplicationImpl{id=nq3a3nshq1}
> (previously had TestEntityImpl{id=cijb9r79z1})
> 2017-11-13 11:45:36,343 INFO succeedsEventually exceeded max attempts or
> timeout - 75 attempts lasting 30000 ms, for
> RunnableAdapter(org.apache.brooklyn.core.entity.EntityAsserts$2@2eae3041)
> 2017-11-13 11:45:36,344 INFO failed succeeds-eventually, 75 attempts,
> 30000ms elapsed (rethrowing): java.lang.AssertionError: attribute=Sensor:
> primary (org.apache.brooklyn.api.entity.Entity);
> val=TestEntityImpl{id=rg0witaqno}
> 2017-11-13 11:45:36,346 ERROR Failed: java.lang.AssertionError: failed
> succeeds-eventually, 75 attempts, 30001ms elapsed: AssertionError:
> attribute=Sensor: primary (org.apache.brooklyn.api.entity.Entity);
> val=TestEntityImpl{id=rg0witaqno}
> java.lang.AssertionError: failed succeeds-eventually, 75 attempts, 30001ms
> elapsed: AssertionError: attribute=Sensor: primary
> (org.apache.brooklyn.api.entity.Entity); val=TestEntityImpl{id=rg0witaqno}
> at
> org.apache.brooklyn.test.Asserts.succeedsEventually(Asserts.java:1009)
> ~[brooklyn-utils-common-1.0.0-SNAPSHOT.jar:1.0.0-SNAPSHOT]
> Caused by: java.lang.AssertionError: attribute=Sensor: primary
> (org.apache.brooklyn.api.entity.Entity); val=TestEntityImpl{id=rg0witaqno}
> at org.apache.brooklyn.test.Asserts.fail(Asserts.java:755)
> ~[brooklyn-utils-common-1.0.0-SNAPSHOT.jar:1.0.0-SNAPSHOT]
> BasicApplicationImpl{id=nq3a3nshq1} nq3a3nshq1
> displayName = Application (nq3a3nshq1)
> locations = []
> brooklyn.wrapper_app = true
> camp.template.id = WpI0y0hC
> quorum.running = QuorumCheck[require=1,0.0%]
> quorum.up = QuorumCheck[require=1,0.0%]
> application.id: nq3a3nshq1
> entity.id: nq3a3nshq1
> primary: TestEntityImpl{id=rg0witaqno}
> service.isUp: true
> service.state: running
> service.state.expected: running @ 1510573506343 / Mon Nov 13 11:45:06 UTC
> 2017
> Policies:
> ElectPrimaryPolicy{id=gcebjkm4dq, name=null, running=true}
>
> primary.selection.mode[ConfigKey:org.apache.brooklyn.policy.failover.ElectPrimaryConfig$SelectionMode]
> = FAILOVER
>
> primary.stopped.wait.timeout[ConfigKey:org.apache.brooklyn.util.time.Duration]
> = 0ms
> Enrichers:
> Transformer{uniqueTag=service.isUp if no service.notUp.indicators,
> running=true, entity=BasicApplicationImpl{id=nq3a3nshq1}, id=iq1mvcb263}
>
> enricher.sourceSensor[ConfigKey:org.apache.brooklyn.api.sensor.Sensor] =
> Sensor: service.notUp.indicators (java.util.Map)
> enricher.suppressDuplicates[ConfigKey:java.lang.Boolean] = true
>
> enricher.targetSensor[ConfigKey:org.apache.brooklyn.api.sensor.Sensor] =
> Sensor: service.isUp (java.lang.Boolean)
> enricher.transformation[ConfigKey:com.google.common.base.Function]
> =
> if[{Predicates.not(Predicates.isNull())=forPredicate(Predicates.equalTo(0)(sizeFunction(keys)))}]-else[UNCHANGED]
> ComputeServiceState{uniqueTag=service.state.actual, running=true,
> entity=BasicApplicationImpl{id=nq3a3nshq1}, id=d90sql52vz}
>
> ComputeServiceIndicatorsFromChildrenAndMembers{uniqueTag=service-lifecycle-indicators-from-children-and-members,
> running=true, entity=BasicApplicationImpl{id=nq3a3nshq1}, id=g6pgaxo97d}
> enricher.aggregating.fromChildren[ConfigKey:java.lang.Boolean] =
> true
> enricher.aggregating.fromMembers[ConfigKey:java.lang.Boolean] = true
>
> enricher.service_state.children_and_members.quorum.running[ConfigKey:org.apache.brooklyn.util.collections.QuorumCheck]
> = QuorumCheck[all;require=0,100.0%]
>
> enricher.service_state.children_and_members.quorum.up[ConfigKey:org.apache.brooklyn.util.collections.QuorumCheck]
> = QuorumCheck[all;require=0,100.0%]
> PrimaryRunningEnricher{running=true,
> entity=BasicApplicationImpl{id=nq3a3nshq1}, id=wcpg5ordwa}
> TestEntityImpl{id=rg0witaqno} rg0witaqno
> displayName = a
> catalogItemId = item-from-test:0.0.0-SNAPSHOT
> locations = []
> camp.template.id = pfqqeadI
> ha.primary.weight = 1
> application.id: nq3a3nshq1
> catalog.id: item-from-test:0.0.0-SNAPSHOT
> entity.id: rg0witaqno
> service.isUp: true
> service.state: running
> service.state.expected: running @ 1510573506297 / Mon Nov 13 11:45:06
> UTC 2017
> test.attributeAndConfString: defaultval
> Enrichers:
> Transformer{uniqueTag=service.isUp if no service.notUp.indicators,
> running=true, entity=TestEntityImpl{id=rg0witaqno}, id=bjbxe2ddrz}
>
> enricher.sourceSensor[ConfigKey:org.apache.brooklyn.api.sensor.Sensor] =
> Sensor: service.notUp.indicators (java.util.Map)
> enricher.suppressDuplicates[ConfigKey:java.lang.Boolean] = true
>
> enricher.targetSensor[ConfigKey:org.apache.brooklyn.api.sensor.Sensor] =
> Sensor: service.isUp (java.lang.Boolean)
>
> enricher.transformation[ConfigKey:com.google.common.base.Function] =
> if[{Predicates.not(Predicates.isNull())=forPredicate(Predicates.equalTo(0)(sizeFunction(keys)))}]-else[UNCHANGED]
> ComputeServiceState{uniqueTag=service.state.actual, running=true,
> entity=TestEntityImpl{id=rg0witaqno}, id=qdmiyq1sp8}
> TestEntityImpl{id=cijb9r79z1} cijb9r79z1
> displayName = b
> catalogItemId = item-from-test:0.0.0-SNAPSHOT
> locations = []
> camp.template.id = sjvkU3bT
> application.id: nq3a3nshq1
> catalog.id: item-from-test:0.0.0-SNAPSHOT
> entity.id: cijb9r79z1
> ha.primary.weight: 2.0
> service.isUp: true
> service.state: running
> service.state.expected: running @ 1510573506302 / Mon Nov 13 11:45:06
> UTC 2017
> test.attributeAndConfString: defaultval
> Enrichers:
> Transformer{uniqueTag=service.isUp if no service.notUp.indicators,
> running=true, entity=TestEntityImpl{id=cijb9r79z1}, id=h1z8b6pteu}
>
> enricher.sourceSensor[ConfigKey:org.apache.brooklyn.api.sensor.Sensor] =
> Sensor: service.notUp.indicators (java.util.Map)
> enricher.suppressDuplicates[ConfigKey:java.lang.Boolean] = true
>
> enricher.targetSensor[ConfigKey:org.apache.brooklyn.api.sensor.Sensor] =
> Sensor: service.isUp (java.lang.Boolean)
>
> enricher.transformation[ConfigKey:com.google.common.base.Function] =
> if[{Predicates.not(Predicates.isNull())=forPredicate(Predicates.equalTo(0)(sizeFunction(keys)))}]-else[UNCHANGED]
> ComputeServiceState{uniqueTag=service.state.actual, running=true,
> entity=TestEntityImpl{id=cijb9r79z1}, id=n27syuicif}
> Standard Error
> java.lang.AssertionError: failed succeeds-eventually, 75 attempts, 30001ms
> elapsed: AssertionError: attribute=Sensor: primary
> (org.apache.brooklyn.api.entity.Entity); val=TestEntityImpl{id=rg0witaqno}
> at
> org.apache.brooklyn.test.Asserts.succeedsEventually(Asserts.java:1009)
> at org.apache.brooklyn.test.Asserts.succeedsEventually(Asserts.java:892)
> at
> org.apache.brooklyn.core.entity.EntityAsserts.assertAttributeEventually(EntityAsserts.java:93)
> at
> org.apache.brooklyn.core.entity.EntityAsserts.assertAttributeEventually(EntityAsserts.java:88)
> at
> org.apache.brooklyn.camp.brooklyn.test.policy.failover.ElectPrimaryTest.runSelectionModeTest(ElectPrimaryTest.java:334)
> at
> org.apache.brooklyn.camp.brooklyn.test.policy.failover.ElectPrimaryTest.testSelectionModeFailoverReelectWithPreference(ElectPrimaryTest.java:292)
> at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
> at
> sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
> at
> sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
> at java.lang.reflect.Method.invoke(Method.java:498)
> at
> org.testng.internal.MethodInvocationHelper.invokeMethod(MethodInvocationHelper.java:104)
> at org.testng.internal.Invoker.invokeMethod(Invoker.java:645)
> at org.testng.internal.Invoker.invokeTestMethod(Invoker.java:851)
> at org.testng.internal.Invoker.invokeTestMethods(Invoker.java:1177)
> at
> org.testng.internal.TestMethodWorker.invokeTestMethods(TestMethodWorker.java:129)
> at org.testng.internal.TestMethodWorker.run(TestMethodWorker.java:112)
> at org.testng.TestRunner.privateRun(TestRunner.java:756)
> at org.testng.TestRunner.run(TestRunner.java:610)
> at org.testng.SuiteRunner.runTest(SuiteRunner.java:387)
> at org.testng.SuiteRunner.runSequentially(SuiteRunner.java:382)
> at org.testng.SuiteRunner.privateRun(SuiteRunner.java:340)
> at org.testng.SuiteRunner.run(SuiteRunner.java:289)
> at org.testng.SuiteRunnerWorker.runSuite(SuiteRunnerWorker.java:52)
> at org.testng.SuiteRunnerWorker.run(SuiteRunnerWorker.java:86)
> at org.testng.TestNG.runSuitesSequentially(TestNG.java:1293)
> at org.testng.TestNG.runSuitesLocally(TestNG.java:1218)
> at org.testng.TestNG.runSuites(TestNG.java:1133)
> at org.testng.TestNG.run(TestNG.java:1104)
> at
> org.apache.maven.surefire.testng.TestNGExecutor.run(TestNGExecutor.java:132)
> at
> org.apache.maven.surefire.testng.TestNGDirectoryTestSuite.executeMulti(TestNGDirectoryTestSuite.java:193)
> at
> org.apache.maven.surefire.testng.TestNGDirectoryTestSuite.execute(TestNGDirectoryTestSuite.java:94)
> at
> org.apache.maven.surefire.testng.TestNGProvider.invoke(TestNGProvider.java:147)
> at
> org.apache.maven.surefire.booter.ForkedBooter.invokeProviderInSameClassLoader(ForkedBooter.java:290)
> at
> org.apache.maven.surefire.booter.ForkedBooter.runSuitesInProcess(ForkedBooter.java:242)
> at
> org.apache.maven.surefire.booter.ForkedBooter.main(ForkedBooter.java:121)
> Caused by: java.lang.AssertionError: attribute=Sensor: primary
> (org.apache.brooklyn.api.entity.Entity); val=TestEntityImpl{id=rg0witaqno}
> at org.apache.brooklyn.test.Asserts.fail(Asserts.java:755)
> at org.apache.brooklyn.test.Asserts.assertTrue(Asserts.java:734)
> at
> org.apache.brooklyn.core.entity.EntityAsserts.assertAttribute(EntityAsserts.java:103)
> at
> org.apache.brooklyn.core.entity.EntityAsserts$2.run(EntityAsserts.java:95)
> at
> org.apache.brooklyn.test.Asserts$RunnableAdapter.call(Asserts.java:1363)
> at org.apache.brooklyn.test.Asserts.succeedsEventually(Asserts.java:970)
> ... 34 more
> {noformat}
> The underlying reason is that the {{ElectPrimaryEffector}} is executed
> multiple times concurrently (it could be up to three: first from
> {{ElectPrimaryPolicy.setEntity}} calling {{rescanRequest}}, next from a
> change of a child's sensor, and third in the
> {{ElectPrimaryTest.runSelectionModeTest}} when it explicitly calls the
> effector with mode=best; in this case I think it's just the last two; the
> first doesn't happen concurrently because the policy is added before the
> entity is managed).
> When the effectors execute concurrently, the mode=best invocation can set the
> primary first, and then the one triggered by sensor-changed (which had
> already decided who the primary should be) sees that the current-active does
> not match what it thinks.
--
This message was sent by Atlassian JIRA
(v6.4.14#64029)