Skip to content

Commit

Permalink
feat: make replicated data types generic (#327)
Browse files Browse the repository at this point in the history
  • Loading branch information
pvlugter authored May 11, 2022
1 parent fad233b commit 8566a3a
Show file tree
Hide file tree
Showing 17 changed files with 269 additions and 179 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,8 @@ type RemoveShoppingCart = proto.com.example.shoppingcart.RemoveShoppingCart;

type Context = replicatedentity.ReplicatedEntityCommandContext;

type Product = proto.com.example.shoppingcart.domain.IProduct & protobuf.Message;

// end::types[]
// tag::class[]
const entity = new replicatedentity.ReplicatedEntity( // <1>
Expand All @@ -45,7 +47,7 @@ const entity = new replicatedentity.ReplicatedEntity( // <1>
// end::class[]

// tag::defaultValue[]
entity.defaultValue = () => new replicatedentity.ReplicatedCounterMap(); // <1>
entity.defaultValue = () => new replicatedentity.ReplicatedCounterMap<Product>(); // <1>
// end::defaultValue[]

// tag::types[]
Expand All @@ -69,7 +71,7 @@ function addItem(addLineItem: AddLineItem, context: Context) {
return replies.failure(`Quantity for item ${addLineItem.productId} must be greater than zero`); // <1>
}

const cart = context.state as replicatedentity.ReplicatedCounterMap; // <2>
const cart = context.state as replicatedentity.ReplicatedCounterMap<Product>; // <2>

const product = Product.create({
id: addLineItem.productId, // <3>
Expand All @@ -83,7 +85,7 @@ function addItem(addLineItem: AddLineItem, context: Context) {
// end::addItem[]

function removeItem(removeLineItem: RemoveLineItem, context: Context) {
const cart = context.state as replicatedentity.ReplicatedCounterMap;
const cart = context.state as replicatedentity.ReplicatedCounterMap<Product>;

const product = Product.create({
id: removeLineItem.productId,
Expand All @@ -101,7 +103,7 @@ function removeItem(removeLineItem: RemoveLineItem, context: Context) {

// tag::getCart[]
function getCart(getShoppingCart: GetShoppingCart, context: Context) {
const cart = context.state as replicatedentity.ReplicatedCounterMap; // <1>
const cart = context.state as replicatedentity.ReplicatedCounterMap<Product>; // <1>

const items = Array.from(cart.keys()) // <2>
.map(product => ({
Expand Down
18 changes: 18 additions & 0 deletions sdk/bin/compile-protobuf.sh
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,24 @@ $PROTOC \
rm -rf test/proto
cp -r proto test/

pbjs -t static-module -w commonjs \
-o ./test/proto/test-protobuf-bundle.js \
-p ./proto -p ./protoc/include \
./proto/kalix/*.proto \
./proto/kalix/protocol/*.proto \
./proto/kalix/component/*.proto \
./proto/kalix/component/*/*.proto \
./test/*.proto

pbjs -t static-module \
-p ./proto -p ./protoc/include \
./proto/kalix/*.proto \
./proto/kalix/protocol/*.proto \
./proto/kalix/component/*.proto \
./proto/kalix/component/*/*.proto \
./test/*.proto \
| pbts -o ./test/proto/test-protobuf-bundle.d.ts -

OUT_DIR="${PWD}/test/proto"
TS_OUT_DIR="${PWD}/test/proto"

Expand Down
2 changes: 1 addition & 1 deletion sdk/src/event-sourced-entity.ts
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,7 @@ export namespace EventSourcedEntity {
* @param state - The entity state
* @returns The new entity state
*/
export type BehaviorCallback = (state: Serializable) => Behavior;
export type BehaviorCallback = (state: any) => Behavior;

/**
* Initial state callback.
Expand Down
36 changes: 20 additions & 16 deletions sdk/src/replicated-data/counter-map.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,19 +34,23 @@ namespace protocol {
proto.kalix.component.replicatedentity.IReplicatedCounterMapEntryDelta;
}

interface Entry {
key: Serializable;
interface Entry<Key extends Serializable> {
key: Key;
counter: ReplicatedCounter;
}

/**
* A replicated map of counters.
*
* @typeParam Key - Type of keys for the Replicated Counter Map
*
* @public
*/
export class ReplicatedCounterMap implements ReplicatedData {
private counters = new Map<Comparable, Entry>();
private removed = new Map<Comparable, Serializable>();
export class ReplicatedCounterMap<Key extends Serializable = Serializable>
implements ReplicatedData
{
private counters = new Map<Comparable, Entry<Key>>();
private removed = new Map<Comparable, Key>();
private cleared = false;

/**
Expand All @@ -55,7 +59,7 @@ export class ReplicatedCounterMap implements ReplicatedData {
* @param key - The key to get
* @returns The counter value, or undefined if no value is defined at that key
*/
get = (key: Serializable): number | undefined => {
get = (key: Key): number | undefined => {
const entry = this.counters.get(AnySupport.toComparable(key));
return entry !== undefined ? entry.counter.value : undefined;
};
Expand All @@ -66,7 +70,7 @@ export class ReplicatedCounterMap implements ReplicatedData {
* @param key - The key to get
* @returns The counter value as a long, or undefined if no value is defined at that key
*/
getLong = (key: Serializable): Long.Long | undefined => {
getLong = (key: Key): Long.Long | undefined => {
const entry = this.counters.get(AnySupport.toComparable(key));
return entry !== undefined ? entry.counter.longValue : undefined;
};
Expand All @@ -79,9 +83,9 @@ export class ReplicatedCounterMap implements ReplicatedData {
* @returns This counter map
*/
increment = (
key: Serializable,
key: Key,
increment: Long.Long | number,
): ReplicatedCounterMap => {
): ReplicatedCounterMap<Key> => {
this.getOrCreateCounter(key).increment(increment);
return this;
};
Expand All @@ -94,9 +98,9 @@ export class ReplicatedCounterMap implements ReplicatedData {
* @returns This counter map
*/
decrement = (
key: Serializable,
key: Key,
decrement: Long.Long | number,
): ReplicatedCounterMap => {
): ReplicatedCounterMap<Key> => {
this.getOrCreateCounter(key).decrement(decrement);
return this;
};
Expand All @@ -107,7 +111,7 @@ export class ReplicatedCounterMap implements ReplicatedData {
* @param key - The key to check
* @returns True if this counter map contains a value for the given key
*/
has = (key: Serializable): boolean => {
has = (key: Key): boolean => {
return this.counters.has(AnySupport.toComparable(key));
};

Expand All @@ -121,7 +125,7 @@ export class ReplicatedCounterMap implements ReplicatedData {
/**
* Return an (iterable) iterator of the keys of this counter map.
*/
keys = (): IterableIterator<Serializable> => {
keys = (): IterableIterator<Key> => {
return iterators.map(this.counters.values(), (entry) => entry.key);
};

Expand All @@ -132,7 +136,7 @@ export class ReplicatedCounterMap implements ReplicatedData {
* @returns This counter map
*/

delete = (key: Serializable): ReplicatedCounterMap => {
delete = (key: Key): ReplicatedCounterMap<Key> => {
const comparableKey = AnySupport.toComparable(key);
if (this.counters.has(comparableKey)) {
this.counters.delete(comparableKey);
Expand All @@ -146,7 +150,7 @@ export class ReplicatedCounterMap implements ReplicatedData {
*
* @returns This counter map
*/
clear = (): ReplicatedCounterMap => {
clear = (): ReplicatedCounterMap<Key> => {
if (this.counters.size > 0) {
this.cleared = true;
this.counters.clear();
Expand All @@ -155,7 +159,7 @@ export class ReplicatedCounterMap implements ReplicatedData {
return this;
};

private getOrCreateCounter(key: Serializable): ReplicatedCounter {
private getOrCreateCounter(key: Key): ReplicatedCounter {
const comparableKey = AnySupport.toComparable(key);
const entry = this.counters.get(comparableKey);
if (entry) {
Expand Down
Loading

0 comments on commit 8566a3a

Please sign in to comment.