• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

Nanopublication / nanopub-java / 25663196917

11 May 2026 09:55AM UTC coverage: 53.534% (+0.1%) from 53.432%
25663196917

Pull #82

github

web-flow
Merge 40ef96265 into fa18b96da
Pull Request #82: feat(server): gate registry instances on Nanopub-Registry-Status

1271 of 3286 branches covered (38.68%)

Branch coverage included in aggregate %.

5651 of 9644 relevant lines covered (58.6%)

8.23 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

39.29
src/main/java/org/nanopub/extra/server/ServerIterator.java
1
package org.nanopub.extra.server;
2

3
import org.nanopub.extra.server.RegistryInfo.RegistryInfoException;
4

5
import java.io.*;
6
import java.util.*;
7

8
/**
9
 * An iterator that provides access to a list of nanopub servers.
10
 */
11
public class ServerIterator implements Iterator<RegistryInfo> {
12

13
    private static Map<String, RegistryInfo> serverInfos = new HashMap<>();
12✔
14
    private static long serverInfoRefreshed = System.currentTimeMillis();
9✔
15
    private static final long serverInfoRefreshInterval = 24 * 60 * 60 * 1000;
16

17
    private List<RegistryInfo> cachedServers = null;
9✔
18
    private List<String> serversToContact = new ArrayList<>();
15✔
19
    private Map<String, Boolean> serversContacted = new HashMap<>();
15✔
20
    private RegistryInfo next = null;
9✔
21

22
    /**
23
     * Creates a new ServerIterator.
24
     */
25
    public ServerIterator() {
26
        this(false);
×
27
    }
×
28

29
    /**
30
     * Creates a new ServerIterator, optionally forcing a reload of the server list.
31
     *
32
     * @param forceServerReload if true, forces a reload of the server list from the cache
33
     */
34
    public ServerIterator(boolean forceServerReload) {
×
35
        if (!forceServerReload) {
×
36
            try {
37
                loadCachedServers();
×
38
            } catch (Exception ex) {
×
39
            }
×
40
        }
41
        if (cachedServers == null) {
×
42
            serversToContact.addAll(NanopubServerUtils.getRegistryServerList());
×
43
        }
44
    }
×
45

46
    /**
47
     * Creates a new ServerIterator with a list of bootstrap servers.
48
     *
49
     * @param bootstrapServers the bootstrap server URLs
50
     */
51
    public ServerIterator(String... bootstrapServers) {
×
52
        serversToContact.addAll(Arrays.asList(bootstrapServers));
×
53
    }
×
54

55
    /**
56
     * Creates a new ServerIterator with a list of bootstrap servers.
57
     *
58
     * @param bootstrapServers the list of bootstrap server URLs
59
     */
60
    public ServerIterator(List<String> bootstrapServers) {
6✔
61
        serversToContact.addAll(bootstrapServers);
15✔
62
    }
3✔
63

64
    /**
65
     * {@inheritDoc}
66
     * <p>
67
     * Checks if there are more servers to iterate over.
68
     */
69
    @Override
70
    public boolean hasNext() {
71
        if (next == null) {
9!
72
            next = getNextServer();
12✔
73
        }
74
        return next != null;
18!
75
    }
76

77
    /**
78
     * {@inheritDoc}
79
     * <p>
80
     * Returns the next server in the iteration.
81
     */
82
    @Override
83
    public RegistryInfo next() {
84
        RegistryInfo n = next;
9✔
85
        next = null;
9✔
86
        if (n == null) {
6!
87
            n = getNextServer();
×
88
        }
89
        return n;
6✔
90
    }
91

92
    /**
93
     * {@inheritDoc}
94
     * <p>
95
     * Removes the current server from the iteration.
96
     */
97
    @Override
98
    public void remove() {
99
        throw new UnsupportedOperationException();
×
100
    }
101

102
    private RegistryInfo getNextServer() {
103
        if (cachedServers != null) {
9!
104
            while (!cachedServers.isEmpty()) {
×
105
                RegistryInfo info = cachedServers.removeFirst();
×
106
                if (NanopubServerUtils.isRegistryEvicted(info.getUrl())) continue;
×
107
                return info;
×
108
            }
109
            return null;
×
110
        } else {
111
            while (!serversToContact.isEmpty()) {
12!
112
                String url = serversToContact.removeFirst();
15✔
113
                if (serversContacted.containsKey(url)) continue;
15!
114
                serversContacted.put(url, true);
21✔
115
                if (NanopubServerUtils.isRegistryEvicted(url)) continue;
9!
116
                RegistryInfo info = getServerInfo(url);
12✔
117
                if (info == null) continue;
6!
118
                return info;
6✔
119
            }
120
        }
121
        return null;
×
122
    }
123

124
    private RegistryInfo getServerInfo(String url) {
125
        if (System.currentTimeMillis() - serverInfoRefreshed > serverInfoRefreshInterval) {
18!
126
            serverInfos.clear();
×
127
            serverInfoRefreshed = System.currentTimeMillis();
×
128
        }
129
        if (!serverInfos.containsKey(url)) {
12✔
130
            try {
131
                RegistryInfo info = RegistryInfo.load(url);
9✔
132
                if (!NanopubServerUtils.isReadyRegistryStatus(info.getStatus())) {
12!
133
                    NanopubServerUtils.evictRegistry(url, "status " + info.getStatus());
×
134
                    return null;
×
135
                }
136
                serverInfos.put(url, info);
15✔
137
            } catch (RegistryInfoException ex) {
×
138
                // ignore
139
            }
3✔
140
        }
141
        return serverInfos.get(url);
15✔
142
    }
143

144
    @SuppressWarnings("unchecked")
145
    private void loadCachedServers() throws Exception {
146
        File serverListFile = getServerListFile();
×
147
        if (serverListFile.exists()) {
×
148
            long now = System.currentTimeMillis();
×
149
            long fileTime = serverListFile.lastModified();
×
150
            if (fileTime > now || now - fileTime > 1000 * 60 * 60 * 24) {
×
151
                return;
×
152
            }
153
            try (ObjectInputStream oin = new ObjectInputStream(new FileInputStream(serverListFile))) {
×
154
                cachedServers = (List<RegistryInfo>) oin.readObject();
×
155
            }
156
        }
157
    }
×
158

159
    /**
160
     * Writes the cached servers to a file.
161
     *
162
     * @param cachedServers the list of cached servers to write
163
     * @throws java.io.IOException if an I/O error occurs
164
     */
165
    public static void writeCachedServers(List<RegistryInfo> cachedServers) throws IOException {
166
        if (cachedServers.size() < 5) return;
×
167
        File serverListFile = getServerListFile();
×
168
        serverListFile.getParentFile().mkdir();
×
169
        try (ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(serverListFile))) {
×
170
            oos.writeObject(cachedServers);
×
171
        }
172
    }
×
173

174
    private static File getServerListFile() {
175
        return new File(System.getProperty("user.home") + "/.nanopub/cachedservers");
×
176
    }
177

178
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc