package io.muoncore.spring.teststore;
import io.muoncore.MultiTransportMuon;
import io.muoncore.protocol.event.Event;
import io.muoncore.protocol.event.server.EventServerProtocolStack;
import io.muoncore.protocol.reactivestream.server.PublisherLookup;
import io.muoncore.spring.annotations.EnableMuon;
import io.muoncore.spring.annotations.MuonController;
import org.reactivestreams.Subscriber;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import javax.annotation.PostConstruct;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import java.util.Queue;
import java.util.concurrent.Executor;
import java.util.concurrent.Executors;
/**
* Implementation of a muon event store that is simplistic to the point of being fairly broken.
* Needs a threading overhaul.
* Useful for simple local testing, use photon for anything else, which has correct threading semantics.
*/
@SpringBootApplication
@MuonController
@EnableMuon(serviceName = "chronos", tags = {"eventstore"})
public class EventStoreInMem {
@Autowired public MultiTransportMuon muon;
private List<Event> history = new ArrayList<>();
private List<SubQueue> subs = new ArrayList<>();
private final Executor exec = Executors.newFixedThreadPool(10);
@PostConstruct
public void setupEventStore() {
exec.execute(() -> {
try {
while(true) {
synchronized (exec) {
exec.wait(500);
//drain all the queues
subs.stream().forEach(sq -> {
synchronized (sq.queue) {
while(sq.queue.size() > 0) {
sq.sub.onNext(sq.queue.poll());
}
}
});
}
}
} catch (InterruptedException e) {
e.printStackTrace();
}
});
muon.getProtocolStacks().registerServerProtocol(new EventServerProtocolStack(event -> {
try {
subs.stream().forEach(q -> {
synchronized (q.queue) {
q.queue.add(event.getEvent());
}
});
synchronized (history) {
history.add(event.getEvent());
}
synchronized (exec) {
exec.notifyAll();
}
event.persisted(12313, System.currentTimeMillis());
} catch (Exception ex) {
event.failed(ex.getMessage());
}
}, muon.getCodecs(), muon.getDiscovery()));
muon.publishGeneratedSource("general", PublisherLookup.PublisherType.HOT_COLD, subscriptionRequest -> {
return subscriber -> {
Queue<Event> queue = new LinkedList<>();
synchronized (history) {
history.stream().forEach(queue::add);
}
subs.add(new SubQueue(queue, subscriber));
};
});
}
static class SubQueue {
Queue<Event> queue;
Subscriber<Event> sub;
public SubQueue(Queue queue, Subscriber sub) {
this.queue = queue;
this.sub = sub;
}
}
public static void main(String[] args) {
SpringApplication.run(EventStoreInMem.class);
}
}