Return-Path: X-Original-To: archive-asf-public-internal@cust-asf2.ponee.io Delivered-To: archive-asf-public-internal@cust-asf2.ponee.io Received: from cust-asf.ponee.io (cust-asf.ponee.io [163.172.22.183]) by cust-asf2.ponee.io (Postfix) with ESMTP id 9A1EA200AE4 for ; Thu, 9 Jun 2016 11:04:54 +0200 (CEST) Received: by cust-asf.ponee.io (Postfix) id 98DB9160A2B; Thu, 9 Jun 2016 09:04:54 +0000 (UTC) Delivered-To: archive-asf-public@cust-asf.ponee.io Received: from mail.apache.org (hermes.apache.org [140.211.11.3]) by cust-asf.ponee.io (Postfix) with SMTP id C55A1160A58 for ; Thu, 9 Jun 2016 11:04:53 +0200 (CEST) Received: (qmail 924 invoked by uid 500); 9 Jun 2016 09:04:53 -0000 Mailing-List: contact commits-help@brooklyn.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: dev@brooklyn.apache.org Delivered-To: mailing list commits@brooklyn.apache.org Received: (qmail 910 invoked by uid 99); 9 Jun 2016 09:04:53 -0000 Received: from git1-us-west.apache.org (HELO git1-us-west.apache.org) (140.211.11.23) by apache.org (qpsmtpd/0.29) with ESMTP; Thu, 09 Jun 2016 09:04:53 +0000 Received: by git1-us-west.apache.org (ASF Mail Server at git1-us-west.apache.org, from userid 33) id BB0A1DFD4C; Thu, 9 Jun 2016 09:04:52 +0000 (UTC) Content-Type: text/plain; charset="us-ascii" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit From: aledsage@apache.org To: commits@brooklyn.apache.org Date: Thu, 09 Jun 2016 09:04:52 -0000 Message-Id: <04032706620343a896e0a60dce89e6d6@git.apache.org> X-Mailer: ASF-Git Admin Mailer Subject: [1/2] brooklyn-server git commit: Add AbstractTransformer.ALLOW_CYCLIC_PUBLISHING archived-at: Thu, 09 Jun 2016 09:04:54 -0000 Repository: brooklyn-server Updated Branches: refs/heads/master 88df98d5a -> 0150e2b7c Add AbstractTransformer.ALLOW_CYCLIC_PUBLISHING If set to true, then allows the transformer to read and publish on the same sensor. This is needed for some use-cases in brooklyncentral/advanced-networking. Project: http://git-wip-us.apache.org/repos/asf/brooklyn-server/repo Commit: http://git-wip-us.apache.org/repos/asf/brooklyn-server/commit/544c73e9 Tree: http://git-wip-us.apache.org/repos/asf/brooklyn-server/tree/544c73e9 Diff: http://git-wip-us.apache.org/repos/asf/brooklyn-server/diff/544c73e9 Branch: refs/heads/master Commit: 544c73e9700969471bef872722b555e1435db058 Parents: 8dc292b Author: Aled Sage Authored: Thu Jun 9 01:06:10 2016 +0100 Committer: Aled Sage Committed: Thu Jun 9 10:03:37 2016 +0100 ---------------------------------------------------------------------- .../enricher/stock/AbstractTransformer.java | 30 +++++++++++----- .../stock/TransformingEnricherTest.java | 38 ++++++++++++++++---- 2 files changed, 54 insertions(+), 14 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/544c73e9/core/src/main/java/org/apache/brooklyn/enricher/stock/AbstractTransformer.java ---------------------------------------------------------------------- diff --git a/core/src/main/java/org/apache/brooklyn/enricher/stock/AbstractTransformer.java b/core/src/main/java/org/apache/brooklyn/enricher/stock/AbstractTransformer.java index a9c6d07..ca68266 100644 --- a/core/src/main/java/org/apache/brooklyn/enricher/stock/AbstractTransformer.java +++ b/core/src/main/java/org/apache/brooklyn/enricher/stock/AbstractTransformer.java @@ -59,6 +59,14 @@ public abstract class AbstractTransformer extends AbstractEnricher implemen "Sensors that will trigger re-evaluation", ImmutableList.>of()); + public static final ConfigKey ALLOW_CYCLIC_PUBLISHING = ConfigKeys.newBooleanConfigKey( + "enricher.allowCyclicPublishing", + "Whether to all a transformer to publish to the same sensor (on the same entity) to " + + "which it's subscribed, thus risking an infinite loop. Defaults to false. " + + "Use with caution (e.g. if transformer implementation is very selective about " + + "when to publish, filters out duplicates, etc", + false); + protected Entity producer; protected Sensor sourceSensor; protected Sensor targetSensor; @@ -84,14 +92,20 @@ public abstract class AbstractTransformer extends AbstractEnricher implemen throw new IllegalArgumentException("Enricher "+JavaClassNames.simpleClassName(this)+" has no "+SOURCE_SENSOR.getName()+" and no "+TRIGGER_SENSORS.getName()); } if (producer.equals(entity) && (targetSensor.equals(sourceSensor) || triggerSensors.contains(targetSensor))) { - // We cannot call getTransformation() here to log the tranformation, as it will attempt - // to resolve the transformation, which will cause the entity initialization thread to block - LOG.error("Refusing to add an enricher which reads and publishes on the same sensor: "+ - producer+"->"+targetSensor+" (computing transformation with "+JavaClassNames.simpleClassName(this)+")"); - // we don't throw because this error may manifest itself after a lengthy deployment, - // and failing it at that point simply because of an enricher is not very pleasant - // (at least not until we have good re-run support across the board) - return; + boolean allowCyclicPublishing = Boolean.TRUE.equals(getConfig(ALLOW_CYCLIC_PUBLISHING)); + if (allowCyclicPublishing) { + LOG.debug("Permitting cyclic publishing, though detected enricher will read and publish on the same sensor: "+ + producer+"->"+targetSensor+" (computing transformation with "+JavaClassNames.simpleClassName(this)+")"); + } else { + // We cannot call getTransformation() here to log the tranformation, as it will attempt + // to resolve the transformation, which will cause the entity initialization thread to block + LOG.error("Refusing to add an enricher which reads and publishes on the same sensor: "+ + producer+"->"+targetSensor+" (computing transformation with "+JavaClassNames.simpleClassName(this)+")"); + // we don't throw because this error may manifest itself after a lengthy deployment, + // and failing it at that point simply because of an enricher is not very pleasant + // (at least not until we have good re-run support across the board) + return; + } } if (sourceSensor != null) { http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/544c73e9/core/src/test/java/org/apache/brooklyn/enricher/stock/TransformingEnricherTest.java ---------------------------------------------------------------------- diff --git a/core/src/test/java/org/apache/brooklyn/enricher/stock/TransformingEnricherTest.java b/core/src/test/java/org/apache/brooklyn/enricher/stock/TransformingEnricherTest.java index e47d268..591446d 100644 --- a/core/src/test/java/org/apache/brooklyn/enricher/stock/TransformingEnricherTest.java +++ b/core/src/test/java/org/apache/brooklyn/enricher/stock/TransformingEnricherTest.java @@ -24,6 +24,7 @@ import org.apache.brooklyn.api.entity.EntitySpec; import org.apache.brooklyn.api.sensor.AttributeSensor; import org.apache.brooklyn.api.sensor.EnricherSpec; import org.apache.brooklyn.api.sensor.Sensor; +import org.apache.brooklyn.core.entity.Entities; import org.apache.brooklyn.core.entity.EntityAsserts; import org.apache.brooklyn.core.location.SimulatedLocation; import org.apache.brooklyn.core.sensor.BasicAttributeSensor; @@ -46,7 +47,10 @@ import com.google.common.collect.ImmutableMap; public class TransformingEnricherTest extends BrooklynAppUnitTestSupport { public static final Logger log = LoggerFactory.getLogger(TransformingEnricherTest.class); - + + private static final Duration SHORT_WAIT = Duration.millis(250); + private static final Duration VERY_SHORT_WAIT = Duration.millis(100); + TestEntity producer; AttributeSensor intSensorA; AttributeSensor intSensorB; @@ -175,7 +179,7 @@ public class TransformingEnricherTest extends BrooklynAppUnitTestSupport { // Short wait; expect us to never re-publish the source-sensor as that would cause infinite loop. producer.sensors().set(intSensorA, 1); - EntityAsserts.assertAttributeEqualsContinually(ImmutableMap.of("timeout", Duration.millis(250)), producer, intSensorA, 1); + EntityAsserts.assertAttributeEqualsContinually(ImmutableMap.of("timeout", SHORT_WAIT), producer, intSensorA, 1); } @Test @@ -194,7 +198,7 @@ public class TransformingEnricherTest extends BrooklynAppUnitTestSupport { }})); producer.sensors().set(intSensorA, 1); - EntityAsserts.assertAttributeEqualsContinually(ImmutableMap.of("timeout", Duration.millis(250)), producer, intSensorA, 1); + EntityAsserts.assertAttributeEqualsContinually(ImmutableMap.of("timeout", SHORT_WAIT), producer, intSensorA, 1); } @Test @@ -225,17 +229,39 @@ public class TransformingEnricherTest extends BrooklynAppUnitTestSupport { EntityAsserts.assertAttributeEqualsEventually(app, intSensorA, 3); } + @Test + public void testAllowCyclicPublishing() throws Exception { + app.enrichers().add(EnricherSpec.create(Transformer.class) + .configure(Transformer.SOURCE_SENSOR, intSensorA) + .configure(Transformer.TARGET_SENSOR, intSensorA) + .configure(Transformer.ALLOW_CYCLIC_PUBLISHING, true) + .configure(Transformer.TRANSFORMATION_FROM_VALUE, new Function() { + @Override public Object apply(Integer input) { + if (input != null && input < 10) { + return input + 1; + } else { + return Entities.UNCHANGED; + } + }})); + + app.sensors().set(intSensorA, 3); + + EntityAsserts.assertAttributeEqualsEventually(app, intSensorA, 10); + EntityAsserts.assertAttributeEqualsContinually(ImmutableMap.of("timeout", VERY_SHORT_WAIT), app, intSensorA, 10); + } + + @Test public void testTransformerFailsWithEmptyConfig() throws Exception { EnricherSpec spec = EnricherSpec.create(Transformer.class); - assertAddEnricherThrowsNullPointerException(spec, "Value required"); + assertAddEnricherThrowsIllegalArgumentException(spec, "Transformer has no"); } - private void assertAddEnricherThrowsNullPointerException(EnricherSpec spec, String expectedPhrase) { + private void assertAddEnricherThrowsIllegalArgumentException(EnricherSpec spec, String expectedPhrase) { try { app.enrichers().add(spec); Asserts.shouldHaveFailedPreviously(); - } catch (NullPointerException e) { + } catch (IllegalArgumentException e) { Asserts.expectedFailureContains(e, expectedPhrase); } }