Move LeaderInitiators to later phase
There is a race condition when Zookeeper `LeaderInitiator` may start earlier than `CuratorFramework` it depends on. This is because both of them are configured for the same default `phase` (`0`) * Make `LeaderInitiator` and `LockRegistryLeaderInitiator` to be started in the `Integer.MAX_VALUE - 1000` phase by default - as late as possible * Make `CuratorFrameworkFactoryBean` to start in the `Integer.MIN_VALUE + 1000` phase - as early as possible * Alight lifecycle properties from the `LeaderInitiatorFactoryBean` with defaults in the `LeaderInitiator` * Simplify a `LeaderListenerParser` to rely on the `LeaderInitiatorFactoryBean` **Cherry-pick to 5.0.x**
This commit is contained in:
committed by
Gary Russell
parent
ed07777b4e
commit
15eae700a3
@@ -151,7 +151,7 @@ public class LockRegistryLeaderInitiator implements SmartLifecycle, DisposableBe
|
||||
/**
|
||||
* @see SmartLifecycle which is an extension of org.springframework.context.Phased
|
||||
*/
|
||||
private int phase;
|
||||
private int phase = Integer.MAX_VALUE - 1000;
|
||||
|
||||
/**
|
||||
* Flag that indicates whether the leadership election for this {@link #candidate} is
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2015-2016 the original author or authors.
|
||||
* Copyright 2015-2018 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -27,10 +27,11 @@ import org.springframework.context.SmartLifecycle;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* A spring-friendly way to build a {@link CuratorFramework} and implementing {@link SmartLifecycle}.
|
||||
* A Spring-friendly way to build a {@link CuratorFramework} and implementing {@link SmartLifecycle}.
|
||||
*
|
||||
* @author Gary Russell
|
||||
* @author Artem Bilan
|
||||
*
|
||||
* @since 4.2
|
||||
*/
|
||||
public class CuratorFrameworkFactoryBean implements FactoryBean<CuratorFramework>, SmartLifecycle {
|
||||
@@ -42,18 +43,18 @@ public class CuratorFrameworkFactoryBean implements FactoryBean<CuratorFramework
|
||||
/**
|
||||
* @see SmartLifecycle
|
||||
*/
|
||||
private volatile boolean autoStartup = true;
|
||||
private boolean autoStartup = true;
|
||||
|
||||
/**
|
||||
* @see SmartLifecycle
|
||||
*/
|
||||
private int phase = Integer.MIN_VALUE + 1000;
|
||||
|
||||
/**
|
||||
* @see SmartLifecycle
|
||||
*/
|
||||
private volatile boolean running;
|
||||
|
||||
/**
|
||||
* @see SmartLifecycle
|
||||
*/
|
||||
private volatile int phase;
|
||||
|
||||
|
||||
/**
|
||||
* Construct an instance using the supplied connection string and using a default
|
||||
@@ -135,7 +136,7 @@ public class CuratorFrameworkFactoryBean implements FactoryBean<CuratorFramework
|
||||
}
|
||||
|
||||
@Override
|
||||
public CuratorFramework getObject() throws Exception {
|
||||
public CuratorFramework getObject() {
|
||||
return this.client;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2015-2016 the original author or authors.
|
||||
* Copyright 2015-2018 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -36,6 +36,7 @@ import org.springframework.integration.zookeeper.leader.LeaderInitiator;
|
||||
*
|
||||
* @author Gary Russell
|
||||
* @author Artem Bilan
|
||||
*
|
||||
* @since 4.2
|
||||
*/
|
||||
public class LeaderInitiatorFactoryBean
|
||||
@@ -51,7 +52,7 @@ public class LeaderInitiatorFactoryBean
|
||||
|
||||
private boolean autoStartup = true;
|
||||
|
||||
private int phase;
|
||||
private int phase = Integer.MAX_VALUE - 1000;
|
||||
|
||||
private ApplicationEventPublisher applicationEventPublisher;
|
||||
|
||||
@@ -136,11 +137,11 @@ public class LeaderInitiatorFactoryBean
|
||||
if (this.leaderInitiator != null) {
|
||||
return this.leaderInitiator.getPhase();
|
||||
}
|
||||
return 0;
|
||||
return this.phase;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void afterPropertiesSet() throws Exception {
|
||||
public void afterPropertiesSet() {
|
||||
if (this.leaderInitiator == null) {
|
||||
this.leaderInitiator = new LeaderInitiator(this.client, this.candidate, this.path);
|
||||
this.leaderInitiator.setPhase(this.phase);
|
||||
@@ -156,7 +157,7 @@ public class LeaderInitiatorFactoryBean
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized LeaderInitiator getObject() throws Exception {
|
||||
public synchronized LeaderInitiator getObject() {
|
||||
return this.leaderInitiator;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2015-2016 the original author or authors.
|
||||
* Copyright 2015-2018 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -16,8 +16,6 @@
|
||||
|
||||
package org.springframework.integration.zookeeper.config.xml;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
import org.w3c.dom.Element;
|
||||
|
||||
import org.springframework.beans.factory.support.AbstractBeanDefinition;
|
||||
@@ -25,12 +23,12 @@ import org.springframework.beans.factory.support.BeanDefinitionBuilder;
|
||||
import org.springframework.beans.factory.xml.AbstractBeanDefinitionParser;
|
||||
import org.springframework.beans.factory.xml.ParserContext;
|
||||
import org.springframework.integration.config.xml.IntegrationNamespaceUtils;
|
||||
import org.springframework.integration.leader.DefaultCandidate;
|
||||
import org.springframework.integration.leader.event.DefaultLeaderEventPublisher;
|
||||
import org.springframework.integration.zookeeper.leader.LeaderInitiator;
|
||||
import org.springframework.integration.zookeeper.config.LeaderInitiatorFactoryBean;
|
||||
|
||||
/**
|
||||
* @author Gary Russell
|
||||
* @author Artem Bilan
|
||||
*
|
||||
* @since 4.2
|
||||
*
|
||||
*/
|
||||
@@ -38,20 +36,14 @@ public class LeaderListenerParser extends AbstractBeanDefinitionParser {
|
||||
|
||||
@Override
|
||||
protected AbstractBeanDefinition parseInternal(Element element, ParserContext parserContext) {
|
||||
BeanDefinitionBuilder candidateBuilder = BeanDefinitionBuilder.genericBeanDefinition(DefaultCandidate.class);
|
||||
candidateBuilder.addConstructorArgValue(UUID.randomUUID().toString());
|
||||
candidateBuilder.addConstructorArgValue(element.getAttribute("role"));
|
||||
BeanDefinitionBuilder builder =
|
||||
BeanDefinitionBuilder.genericBeanDefinition(LeaderInitiatorFactoryBean.class)
|
||||
.addPropertyReference("client", element.getAttribute("client"))
|
||||
.addPropertyValue("role", element.getAttribute(IntegrationNamespaceUtils.ROLE))
|
||||
.addPropertyValue("path", element.getAttribute("path"));
|
||||
|
||||
BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition(LeaderInitiator.class);
|
||||
builder.addConstructorArgReference(element.getAttribute("client"));
|
||||
builder.addConstructorArgValue(candidateBuilder.getBeanDefinition());
|
||||
builder.addConstructorArgValue(element.getAttribute("path"));
|
||||
IntegrationNamespaceUtils.setValueIfAttributeDefined(builder, element, "auto-startup");
|
||||
IntegrationNamespaceUtils.setValueIfAttributeDefined(builder, element, "phase");
|
||||
|
||||
BeanDefinitionBuilder publisherBuilder = BeanDefinitionBuilder
|
||||
.genericBeanDefinition(DefaultLeaderEventPublisher.class);
|
||||
builder.addPropertyValue("leaderEventPublisher", publisherBuilder.getBeanDefinition());
|
||||
IntegrationNamespaceUtils.setValueIfAttributeDefined(builder, element, IntegrationNamespaceUtils.AUTO_STARTUP);
|
||||
IntegrationNamespaceUtils.setValueIfAttributeDefined(builder, element, IntegrationNamespaceUtils.PHASE);
|
||||
|
||||
return builder.getBeanDefinition();
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2014-2017 the original author or authors.
|
||||
* Copyright 2014-2018 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -88,7 +88,7 @@ public class LeaderInitiator implements SmartLifecycle {
|
||||
/**
|
||||
* @see SmartLifecycle which is an extension of org.springframework.context.Phased
|
||||
*/
|
||||
private volatile int phase;
|
||||
private volatile int phase = Integer.MAX_VALUE - 1000;
|
||||
|
||||
/**
|
||||
* Flag that indicates whether the leadership election for
|
||||
|
||||
Reference in New Issue
Block a user