Last active
December 6, 2022 15:47
-
-
Save 1ou/664eec085548fac8c7f26ecae754fd18 to your computer and use it in GitHub Desktop.
revolut
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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