io.descoped.rawdata.api.RawdataMessage Maven / Gradle / Ivy
package io.descoped.rawdata.api;
import de.huxhorn.sulky.ulid.ULID;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Set;
import java.util.function.Function;
import java.util.stream.Collectors;
public interface RawdataMessage {
static RawdataMessage.Builder builder() {
return new RawdataDefaultMessage.Builder();
}
RawdataMessage.Builder copy();
/**
* A unique lexicographically sortable identifier for the message. Sorting by this id, will also sort the messages
* by time, making it convenient
*
* @return
*/
ULID.Value ulid();
/**
* Timestamp represented as milliseconds since 1/1-1970. This is derived from the ulid.
*
* @return
*/
default long timestamp() {
return ulid().timestamp();
}
/**
* A group used to maintain which messages belong to the same sequence. The sequence of messages within the same
* ordering-group is guaranteed. If there are multiple producers using the same ordering-group on the same topic,
* then either the underlying technology must maintain order (in which the sequenceNumber can be 0), or the
* producers must synchronize externally to ensure that the sequence-numbers are strictly increasing by 1 for each
* next message in the stream belonging to the same ordering-group.
*
* @return the ordering group.
*/
String orderingGroup();
/**
* A sequence-number (greater-than 0) within the stream, or 0 if the stream already guarantees ordering.
*
* These sequence numbers are based on a counter that starts at 1 and increases by 1 for each message in the ordered
* stream. Because there will be no gaps in this sequence, it's possible for the consumer to re-order the messages
* in a timely manner when using streaming technology where ordering is not guaranteed, but a best-effort thing.
*
* @return the sequence number
*/
long sequenceNumber();
/**
* The original external identifier for the streaming element. Typically the one used by the stream source system.
* This identifier does not need to be sortable.
*
* @return the position
*/
String position();
/**
* A set of content-keys for this message. Use the get() method to get the corresponding content-value.
*
* @return the content-keys
*/
Set keys();
/**
* Get the content for a given key.
*
* @param key the content-key
* @return the raw bytes of the content
*/
byte[] get(String key);
/**
* Convenience method to get a map of all the content key value mappings.
*
* @return a map of the data.
*/
default Map data() {
return keys().stream().collect(Collectors.toMap(Function.identity(), this::get, (a, b) -> a, LinkedHashMap::new));
}
/**
* Builder used to build messages.
*/
interface Builder {
/**
* Assign an ordering-group to this message. Messages within the same ordering-group (those that provide the same
* value for the group parameter) will be re-ordered by consumers if necessary to guarantee fifo ordering within
* each group.
*
* @param orderingGroup the name of the group, must be unique
* @return this builder
*/
Builder orderingGroup(String orderingGroup);
/**
* @return the group that this message will belong to or null if none has been assigned
*/
String orderingGroup();
/**
* Assign the sequence-number > 0. 0 will be used if none is assigned.
*
* @param sequenceNumber
* @return this builder
* @throws IllegalArgumentException if the sequenceNumber is less than 1.
*/
Builder sequenceNumber(long sequenceNumber);
/**
* @return the sequence number
*/
long sequenceNumber();
/**
* Set ulid value of this message. If not supplied, one will be generated by the publisher at publication time.
* If the sequence-number is not used (value of 0), the ulid value must be strictly monotonically increasing
* from one message to the next message in a stream in order to preserve the correct order of messages. If the
* sequence-number is used, then the ulid value sequencing can be done in a best-effort manner.
*
* @param ulid
* @return this builder
*/
Builder ulid(ULID.Value ulid);
/**
* @return the current ulid
*/
ULID.Value ulid();
/**
* The external identifier of the element in the stream.
*
* @param position
* @return this builder
*/
Builder position(String position);
/**
* @return the current position of this builder
*/
String position();
/**
* Assign binary content to a named key.
*
* @param key the named key
* @param payload the content
* @return this builder
*/
Builder put(String key, byte[] payload);
/**
* Put all values from provided map into internal builder map.
*
* @param data the data
* @return this builder
*/
default Builder data(Map data) {
data.forEach(this::put);
return this;
}
/**
* Get the data map
*/
Map data();
/**
* @return The keys added to this builder through put so far.
*/
Set keys();
/**
* @param key
* @return the current value for the provided key, or null if no such key exists
*/
byte[] get(String key);
/**
* Build a message by the properties defined through previous calls to this builder. If some requirements are
* missing, this call will throw a runtime-exception.
*
* @return the message
*/
RawdataMessage build();
}
}