summaryrefslogtreecommitdiffstats
path: root/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/maintenance/Expirer.java
blob: a8929cf9d22f1a9688143860fb33129f70f1ad8e (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
// Copyright Yahoo. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
package com.yahoo.vespa.hosted.provision.maintenance;

import com.yahoo.jdisc.Metric;
import com.yahoo.vespa.hosted.provision.Node;
import com.yahoo.vespa.hosted.provision.NodeList;
import com.yahoo.vespa.hosted.provision.NodeRepository;
import com.yahoo.vespa.hosted.provision.node.History;

import java.time.Duration;
import java.util.List;
import java.util.logging.Logger;

/**
 * Base class for maintenance of nodes that linger in a particular state too long.
 *
 * @author bratseth
 */
public abstract class Expirer extends NodeRepositoryMaintainer {

    protected static final Logger log = Logger.getLogger(Expirer.class.getName());

    /** The state to expire from */
    private final Node.State fromState;

    /** The event record type which contains the timestamp to use for expiry */
    private final History.Event.Type eventType;

    private final Metric metric;
    private final Duration expiryTime;

    Expirer(Node.State fromState, History.Event.Type eventType, NodeRepository nodeRepository,
            Duration expiryTime, Metric metric) {
        super(nodeRepository, min(Duration.ofMinutes(10), expiryTime), metric);
        this.fromState = fromState;
        this.eventType = eventType;
        this.metric = metric;
        this.expiryTime = expiryTime;
    }

    @Override
    protected double maintain() {
        NodeList expired = nodeRepository().nodes().list(fromState).matching(this::isExpired);

        if ( ! expired.isEmpty()) {
            log.info(fromState + " expirer found " + expired.size() + " expired nodes: " + expired);
            expire(expired.asList());
        }

        metric.add("expired." + fromState, expired.size(), null);
        return 1.0;
    }

    protected boolean isExpired(Node node) {
        return isExpired(node, expiryTime);
    }

    protected final boolean isExpired(Node node, Duration expiryTime) {
        return node.history().hasEventBefore(eventType, clock().instant().minus(expiryTime));
    }

    /** Implement this callback to take action to expire these nodes */
    protected abstract void expire(List<Node> expired);

}