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

feat: Check platform status before syncing #11429

Merged
merged 2 commits into from Feb 8, 2024
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.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
Expand Up @@ -267,7 +267,7 @@ public SyncGossip(
>= eventConfig.eventIntakeQueueThrottleSize(),
Duration.ZERO,
syncMetrics,
time)))))
platformStatusManager)))))
.build());
}

Expand Down
Expand Up @@ -18,7 +18,6 @@

import static com.swirlds.common.utility.CompareTo.isGreaterThanOrEqualTo;

import com.swirlds.base.time.Time;
import com.swirlds.common.context.PlatformContext;
import com.swirlds.common.platform.NodeId;
import com.swirlds.common.threading.pool.ParallelExecutionException;
Expand All @@ -32,11 +31,15 @@
import com.swirlds.platform.network.Connection;
import com.swirlds.platform.network.NetworkProtocolException;
import com.swirlds.platform.network.protocol.Protocol;
import com.swirlds.platform.system.status.PlatformStatus;
import com.swirlds.platform.system.status.PlatformStatusGetter;
import edu.umd.cs.findbugs.annotations.NonNull;
import java.io.IOException;
import java.time.Duration;
import java.time.Instant;
import java.util.Collection;
import java.util.Objects;
import java.util.Set;
import java.util.function.BooleanSupplier;

/**
Expand All @@ -46,6 +49,17 @@
* This object will be instantiated once per peer, and is bidirectional
*/
public class SyncProtocol implements Protocol {
/**
* The platform statuses that permit syncing. If the platform isn't in one of these statuses, no syncs will be
* initiated or accepted
*/
public static final Collection<PlatformStatus> STATUSES_THAT_PERMIT_SYNC = Set.of(
alittley marked this conversation as resolved.
Show resolved Hide resolved
PlatformStatus.ACTIVE,
PlatformStatus.FREEZING,
PlatformStatus.FREEZE_COMPLETE,
PlatformStatus.OBSERVING,
PlatformStatus.CHECKING,
PlatformStatus.RECONNECT_COMPLETE);
/**
* The id of the peer being synced with in this protocol
*/
Expand Down Expand Up @@ -91,24 +105,23 @@ public class SyncProtocol implements Protocol {
*/
private final Duration sleepAfterSync;

/**
* A source of time
*/
private final Time time;

private final PlatformContext platformContext;

private final PlatformStatusGetter platformStatusGetter;

/**
* Constructs a new sync protocol
*
* @param platformContext the platform context
* @param peerId the id of the peer being synced with in this protocol
* @param synchronizer the shadow graph synchronizer, responsible for actually doing the sync
* @param fallenBehindManager manager to determine whether this node has fallen behind
* @param permitProvider provides permits to sync
* @param sleepAfterSync the amount of time to sleep after a sync
* @param syncMetrics metrics tracking syncing
* @param time a source of time
* @param platformContext the platform context
* @param peerId the id of the peer being synced with in this protocol
* @param synchronizer the shadow graph synchronizer, responsible for actually doing the sync
* @param fallenBehindManager manager to determine whether this node has fallen behind
* @param permitProvider provides permits to sync
* @param gossipHalted returns true if gossip is halted, false otherwise
* @param intakeIsTooFull returns true if the intake queue is too full to continue syncing, false otherwise
* @param sleepAfterSync the amount of time to sleep after a sync
* @param syncMetrics metrics tracking syncing
* @param platformStatusGetter provides the current platform status
*/
public SyncProtocol(
@NonNull final PlatformContext platformContext,
Expand All @@ -120,7 +133,7 @@ public SyncProtocol(
@NonNull final BooleanSupplier intakeIsTooFull,
@NonNull final Duration sleepAfterSync,
@NonNull final SyncMetrics syncMetrics,
@NonNull final Time time) {
@NonNull final PlatformStatusGetter platformStatusGetter) {

this.platformContext = Objects.requireNonNull(platformContext);
this.peerId = Objects.requireNonNull(peerId);
Expand All @@ -131,14 +144,15 @@ public SyncProtocol(
this.intakeIsTooFull = Objects.requireNonNull(intakeIsTooFull);
this.sleepAfterSync = Objects.requireNonNull(sleepAfterSync);
this.syncMetrics = Objects.requireNonNull(syncMetrics);
this.time = Objects.requireNonNull(time);
this.platformStatusGetter = Objects.requireNonNull(platformStatusGetter);
}

/**
* @return true if the cooldown period after a sync has elapsed, else false
*/
private boolean syncCooldownComplete() {
final Duration elapsed = Duration.between(lastSyncTime, time.now());
final Duration elapsed =
Duration.between(lastSyncTime, platformContext.getTime().now());

return isGreaterThanOrEqualTo(elapsed, sleepAfterSync);
}
Expand All @@ -149,6 +163,10 @@ private boolean syncCooldownComplete() {
* @return true if the node should sync, false otherwise
*/
private boolean shouldSync() {
if (!STATUSES_THAT_PERMIT_SYNC.contains(platformStatusGetter.getCurrentStatus())) {
syncMetrics.doNotSyncPlatformStatus();
return false;
}

if (!syncCooldownComplete()) {
syncMetrics.doNotSyncCooldown();
Expand Down Expand Up @@ -269,7 +287,7 @@ public void runProtocol(@NonNull final Connection connection)
} finally {
returnPermit();

lastSyncTime = time.now();
lastSyncTime = platformContext.getTime().now();
}
}
}
Expand Up @@ -98,6 +98,12 @@ public class SyncMetrics {
.withDescription("the average time spent filtering events during a sync")
.withUnit("nanoseconds");

private static final CountPerSecond.Config DO_NOT_SYNC_PLATFORM_STATUS = new CountPerSecond.Config(
PLATFORM_CATEGORY, "doNotSyncPlatformStatus")
.withUnit("hz")
.withDescription("Number of times per second we do not sync because the platform status doesn't permit it");
private final CountPerSecond doNoSyncPlatformStatus;

private static final CountPerSecond.Config DO_NOT_SYNC_COOLDOWN_CONFIG = new CountPerSecond.Config(
PLATFORM_CATEGORY, "doNotSyncCooldown")
.withUnit("hz")
Expand Down Expand Up @@ -169,6 +175,7 @@ public SyncMetrics(final Metrics metrics) {
syncsPerSec = new CountPerSecond(metrics, SYNCS_PER_SECOND_CONFIG);
syncFilterTime = metrics.getOrCreate(SYNC_FILTER_TIME_CONFIG);

doNoSyncPlatformStatus = new CountPerSecond(metrics, DO_NOT_SYNC_PLATFORM_STATUS);
doNotSyncCooldown = new CountPerSecond(metrics, DO_NOT_SYNC_COOLDOWN_CONFIG);
doNotSyncHalted = new CountPerSecond(metrics, DO_NOT_SYNC_HALTED_CONFIG);
doNotSyncIntakeQueue = new CountPerSecond(metrics, DO_NOT_SYNC_INTAKE_QUEUE_CONFIG);
Expand Down Expand Up @@ -398,6 +405,13 @@ public void recordSyncFilterTime(final long nanoseconds) {
syncFilterTime.update(nanoseconds);
}

/**
* Signal that we chose not to sync because of the current platform status
*/
public void doNotSyncPlatformStatus() {
doNoSyncPlatformStatus.count();
}

/**
* Signal that we chose not to sync because we are in sync cooldown.
*/
Expand Down