Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Refactor OriginsInventory. #62

Merged
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Address code review comments.
  • Loading branch information
Mikko Karjalainen committed Jan 12, 2018
commit 8c20bae3d0b412ae596dd272e26e93c1ca32c3b7
Original file line number Diff line number Diff line change
Expand Up @@ -57,21 +57,22 @@
import java.util.Optional;
import java.util.Set;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.stream.Stream;

import static com.google.common.base.Preconditions.checkArgument;
import static com.hotels.styx.client.HttpConfig.newHttpConfigBuilder;
import static com.hotels.styx.client.OriginsInventory.OriginState.ACTIVE;
import static com.hotels.styx.client.OriginsInventory.OriginState.DISABLED;
import static com.hotels.styx.client.OriginsInventory.OriginState.INACTIVE;
import static com.hotels.styx.common.StyxFutures.await;
import static java.util.Collections.emptyMap;
import static java.util.Collections.singleton;
import static java.util.Objects.isNull;
import static java.util.Objects.nonNull;
import static java.util.Objects.requireNonNull;
import static java.util.stream.Collectors.toList;
import static java.util.stream.Collectors.toMap;
import static java.util.stream.Collectors.toSet;
import static java.util.stream.Stream.concat;
import static org.slf4j.LoggerFactory.getLogger;

/**
Expand Down Expand Up @@ -100,7 +101,7 @@ public final class OriginsInventory
private final QueueDrainingEventProcessor eventQueue;
private final AtomicBoolean closed = new AtomicBoolean(false);

private Map<Id, MonitoredOrigin> origins = ImmutableMap.of();
private Map<Id, MonitoredOrigin> origins = emptyMap();


/**
Expand Down Expand Up @@ -183,104 +184,101 @@ public void addInventoryStateChangeListener(OriginsInventoryStateChangeListener
inventoryListeners.addListener(listener);
}

public boolean closed() {
return closed.get();
}

@Override
public void submit(Object event) {
if (event instanceof SetOriginsEvent) {
addOriginsEventHandler((SetOriginsEvent) event);
handleSetOriginsEvent((SetOriginsEvent) event);
} else if (event instanceof OriginHealthEvent) {
originHealthEventHandler((OriginHealthEvent) event);
handleOriginHealthEvent((OriginHealthEvent) event);
} else if (event instanceof EnableOriginCommand) {
enableOriginHandler((EnableOriginCommand) event);
handleEnableOriginCommand((EnableOriginCommand) event);
} else if (event instanceof DisableOriginCommand) {
disableOriginHandler((DisableOriginCommand) event);
handleDisableOriginCommand((DisableOriginCommand) event);
} else if (event instanceof CloseEvent) {
closeHandler();
handleCloseEvent();
}
}

private class SetOriginsEvent {
private static class SetOriginsEvent {
final Set<Origin> newOrigins;

public SetOriginsEvent(Set<Origin> newOrigins) {
SetOriginsEvent(Set<Origin> newOrigins) {
this.newOrigins = newOrigins;
}
}

private class OriginHealthEvent {
private static class OriginHealthEvent {
final Object healthEvent;
final Origin origin;

public OriginHealthEvent(Origin origin, Object healthy) {
OriginHealthEvent(Origin origin, Object healthy) {
this.origin = origin;
this.healthEvent = healthy;
}
}

private class EnableOriginCommand {
private static class EnableOriginCommand {
final EnableOrigin enableOrigin;

public EnableOriginCommand(EnableOrigin enableOrigin) {
EnableOriginCommand(EnableOrigin enableOrigin) {
this.enableOrigin = enableOrigin;
}
}

private class DisableOriginCommand {
private static class DisableOriginCommand {
final DisableOrigin disableOrigin;

public DisableOriginCommand(DisableOrigin disableOrigin) {
DisableOriginCommand(DisableOrigin disableOrigin) {
this.disableOrigin = disableOrigin;
}
}

private class CloseEvent {
private static class CloseEvent {

}

public boolean closed() {
return closed.get();
}

public void addOriginsEventHandler(SetOriginsEvent event) {
Set<Origin> newOrigins = event.newOrigins;
Map<Id, Origin> newOriginsMap = newOrigins.stream()
private void handleSetOriginsEvent(SetOriginsEvent event) {
Map<Id, Origin> newOriginsMap = event.newOrigins.stream()
.collect(toMap(Origin::id, o -> o));

Set<Id> allOriginIds = Stream.concat(this.origins.keySet().stream(), newOriginsMap.keySet().stream())
.collect(toSet());

ImmutableMap.Builder<Id, MonitoredOrigin> monitoredOrigins = ImmutableMap.builder();
AtomicBoolean changed = new AtomicBoolean(false);
OriginChanges originChanges = new OriginChanges();

allOriginIds.forEach(
originId -> {
concat(this.origins.keySet().stream(), newOriginsMap.keySet().stream())
.collect(toSet())
.forEach(originId -> {
Origin origin = newOriginsMap.get(originId);

if (isNewOrigin(originId, origin)) {
MonitoredOrigin monitoredOrigin = addMonitoredEndpoint(origin);
monitoredOrigins.put(originId, monitoredOrigin);
changed.set(true);
originChanges.addOrReplaceOrigin(originId, monitoredOrigin);

} else if (isUpdatedOrigin(originId, origin)) {
MonitoredOrigin monitoredOrigin = changeMonitoredEndpoint(origin);
monitoredOrigins.put(originId, monitoredOrigin);
changed.set(true);
originChanges.addOrReplaceOrigin(originId, monitoredOrigin);

} else if (isUnchangedOrigin(originId, origin)) {
LOG.info("Existing origin has been left unchanged. Origin={}:{}", appId, origin);
monitoredOrigins.put(originId, this.origins.get(originId));
originChanges.keepExistingOrigin(originId, this.origins.get(originId));

} else if (isRemovedOrigin(originId, origin)) {
removeMonitoredEndpoint(originId);
changed.set(true);
originChanges.noteRemovedOrigin();
}
}
);

this.origins = monitoredOrigins.build();
this.origins = originChanges.updatedOrigins();

if (changed.get()) {
if (originChanges.changed()) {
notifyStateChange();
}
}

private void closeHandler() {
private void handleCloseEvent() {
if (closed.compareAndSet(false, true)) {
origins.values().forEach(host -> removeMonitoredEndpoint(host.origin.id()));
this.origins = ImmutableMap.of();
Expand All @@ -289,19 +287,19 @@ private void closeHandler() {
}
}

private void disableOriginHandler(DisableOriginCommand event) {
private void handleDisableOriginCommand(DisableOriginCommand event) {
if (event.disableOrigin.forApp(appId)) {
onEvent(event.disableOrigin.originId(), event.disableOrigin);
}
}

private void enableOriginHandler(EnableOriginCommand event) {
private void handleEnableOriginCommand(EnableOriginCommand event) {
if (event.enableOrigin.forApp(appId)) {
onEvent(event.enableOrigin.originId(), event.enableOrigin);
}
}

private void originHealthEventHandler(OriginHealthEvent event) {
private void handleOriginHealthEvent(OriginHealthEvent event) {
if (event.healthEvent == HEALTHY) {
if (!(originHealthStatusMonitor instanceof NoOriginHealthStatusMonitor)) {
onEvent(event.origin, HEALTHY);
Expand Down Expand Up @@ -619,4 +617,30 @@ enum OriginState {
this.gaugeValue = gaugeValue;
}
}

private class OriginChanges {
ImmutableMap.Builder<Id, MonitoredOrigin> monitoredOrigins = ImmutableMap.builder();
AtomicBoolean changed = new AtomicBoolean(false);

void addOrReplaceOrigin(Id originId, MonitoredOrigin origin) {
monitoredOrigins.put(originId, origin);
changed.set(true);
}

void keepExistingOrigin(Id originId, MonitoredOrigin origin) {
monitoredOrigins.put(originId, origin);
}

void noteRemovedOrigin() {
changed.set(true);
}

boolean changed() {
return changed.get();
}

Map<Id, MonitoredOrigin> updatedOrigins() {
return monitoredOrigins.build();
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,7 @@ public void stop() {
* Setting the origins
*/
@Test
public void setNewOrigins() {
public void startsMonitoringNewOrigins() {
inventory.setOrigins(ORIGIN_1, ORIGIN_2);

assertThat(inventory, hasActiveOrigins(2));
Expand Down Expand Up @@ -146,7 +146,7 @@ public void updatesOriginHostName() throws Exception {
}

@Test
public void stopsMonitoringModifiedOrigins() {
public void stopsAndRestartsMonitoringModifiedOrigins() {
Origin originV1 = newOriginBuilder("acme01.com", 80).applicationId(GENERIC_APP).id("acme-01").build();
Origin originV2 = newOriginBuilder("acme02.com", 80).applicationId(GENERIC_APP).id("acme-01").build();

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
/**
* Informed about state changes.
*
* @param <S> State type.
* @param <S> state type
*/
public interface StateChangeListener<S> {
void onStateChange(S oldState, S newState, Object event);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -207,7 +207,7 @@ enum Outcome {
}

/**
* Result or registry reload.
* Result of registry reload.
*/
class ReloadResult {

Expand Down