All Downloads are FREE. Search and download functionalities are using the official Maven repository.

de.otto.synapse.state.ChronicleMapStateRepository Maven / Gradle / Ivy

Go to download

A library used at otto.de to implement Spring Boot based event-sourcing microservices.

The newest version!
package de.otto.synapse.state;

import com.fasterxml.jackson.databind.ObjectMapper;
import net.openhft.chronicle.hash.ChronicleHashClosedException;
import net.openhft.chronicle.map.ChronicleMap;
import net.openhft.chronicle.map.ChronicleMapBuilder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.Optional;

import static de.otto.synapse.translator.ObjectMappers.currentObjectMapper;

/**
 * A {@code StateRepository} that is using a {@code ChronicleMap} to store the event-sourced entities off the heap.
 *
 * 

Suitable for larger amounts of data, without problems because of garbage-collection issues because of the * usage of off-heap memory.

* *

In order to be able to access the {@link #keySet()} of the stored entities, this implementation is storing * a copy of the keys in a separate {@link java.util.concurrent.ConcurrentSkipListSet}

* * @param The type of the event-sourced entities stored in the {@code StateRepository} */ public class ChronicleMapStateRepository extends ConcurrentMapStateRepository { private static final Logger LOG = LoggerFactory.getLogger(ChronicleMapStateRepository.class); private static final int DEFAULT_KEY_SIZE_BYTES = 128; private static final double DEFAULT_VALUE_SIZE_BYTES = 512; private static final long DEFAULT_ENTRY_COUNT = 100_000; private ChronicleMapStateRepository(final String name, final ChronicleMap chronicleMap) { super(name, chronicleMap); } @Override public Optional put(final String key, final V value) { try { return super.put(key, value); } catch (ChronicleHashClosedException e) { LOG.warn("could not put on closed state repository", e); return Optional.empty(); } } @Override public Optional get(final String key) { try { return super.get(key); } catch (ChronicleHashClosedException e) { LOG.warn("could not get on closed state repository", e); return Optional.empty(); } } @Override public long size() { try { return super.size(); } catch (final ChronicleHashClosedException e) { LOG.warn("could not get size on closed state repository", e); return 0; } } public static Builder builder(Class clazz) { return new Builder<>(clazz); } public static final class Builder { private ObjectMapper objectMapper = currentObjectMapper(); private final Class clazz; private String name; private ChronicleMapBuilder chronicleMapBuilder; private boolean customValueMarshaller = false; private Builder(Class clazz) { this.clazz = clazz; this.name = clazz.getSimpleName(); } public Builder withObjectMapper(ObjectMapper val) { objectMapper = val; return this; } public Builder withName(final String val) { name = val; return this; } public Builder withMapBuilder(ChronicleMapBuilder val) { chronicleMapBuilder = val; return this; } public Builder withCustomValueMarshaller(boolean val) { this.customValueMarshaller = val; return this; } public ChronicleMapStateRepository build() { if (chronicleMapBuilder == null) { chronicleMapBuilder = ChronicleMapBuilder.of(String.class, clazz) .averageKeySize(DEFAULT_KEY_SIZE_BYTES) .averageValueSize(DEFAULT_VALUE_SIZE_BYTES) .entries(DEFAULT_ENTRY_COUNT); } boolean doesClassNeedToBeSerialized = clazz != String.class; if (!customValueMarshaller && doesClassNeedToBeSerialized) { chronicleMapBuilder.valueMarshaller(new ChronicleMapBytesMarshaller<>(objectMapper, clazz)); } return new ChronicleMapStateRepository<>(name, chronicleMapBuilder.create()); } } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy