Skip to content

Instantly share code, notes, and snippets.

@1ou
Last active December 6, 2022 15:47
Show Gist options
  • Save 1ou/664eec085548fac8c7f26ecae754fd18 to your computer and use it in GitHub Desktop.
Save 1ou/664eec085548fac8c7f26ecae754fd18 to your computer and use it in GitHub Desktop.
revolut
Implement a service registry, which is a database of services, their instances and their locations.
1 - Register instances
It should be possible to register an instance, identified by an address
Each address should be unique, it should not be possible to register the same address more than once
Service Registry should accept up to 10 addresses
2 - Random invocation
Develop an algorithm that, when invoking the Service Registry's get() method multiple times, should return one backend-instance choosing between the registered ones randomly.
3-Develop an algorithm that, when invoking multiple times the Service Registry on its get() method, should
return one backend-instance choosing between the registered one sequentially (round-robin).
package org.example;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.concurrent.ThreadLocalRandom;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
public abstract class ServiceRegistry implements BasicService {
private final HashMap<String, Service> services;
private final List<String> addresses;
private final Lock lock;
private final int maxServicesSize;
private final PickPositionStrategy pickPositionStrategy;
public ServiceRegistry(int maxServicesSize, PickPositionStrategy pickPositionStrategy) {
this.maxServicesSize = maxServicesSize;
this.services = new HashMap<>(maxServicesSize);
this.addresses = new ArrayList<>(maxServicesSize);
this.lock = new ReentrantLock();
this.pickPositionStrategy = pickPositionStrategy;
}
public Service register(String name, String ip) {
if (name == null || name.isBlank()) {
throw new IllegalStateException("Can't register service without name");
}
if (ip == null || ip.isBlank()) {
throw new IllegalStateException("Can't register service without IP");
}
lock.lock();
try {
if (services.size() >= maxServicesSize) {
throw new IllegalStateException("Can't register service. The registry is full");
}
var service = new Service(ip, name);
var val = services.putIfAbsent(ip, service);
if (val != null) {
throw new IllegalStateException("Service already exists in registry");
} else {
addresses.add(ip);
return service;
}
} finally {
lock.unlock();
}
}
public Service get() {
return services.get(addresses.get(pickPositionStrategy.position() % addresses.size()));
}
interface PickPositionStrategy {
int position();
}
static class RandomPickPositionPositionStrategy implements PickPositionStrategy {
@Override
public int position() {
return ThreadLocalRandom.current().nextInt(Integer.MAX_VALUE);
}
}
static class RoundRobinPickPositionPositionStrategy implements PickPositionStrategy {
private final AtomicInteger cursor = new AtomicInteger(0);
@Override
public int position() {
return cursor.getAndIncrement();
}
}
static class Service {
private final String name;
private final String ip;
public Service(String ip, String name) {
this.ip = ip;
this.name = name;
}
public String getName() {
return name;
}
public String getIp() {
return ip;
}
}
@Override
public void start() {
}
@Override
public void stop() {
this.services.clear();
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment