docker-compose stop adder-1
until [ $(http --check-status :8092/results/peter 2> /dev/null) ]; do echo "Waiting for some results for peter to show up on adder-2..."; sleep 1; done
-until [ $(http --check-status :8092/results/klaus 2> /dev/null) ]; do echo "Waiting for some results for peter to show up on adder-2..."; sleep 1; done
+until [ $(http --check-status :8092/results/klaus 2> /dev/null) ]; do echo "Waiting for some results for klaus to show up on adder-2..."; sleep 1; done
echo "Resultate für adder-2"
http -v --pretty none -S :8092/results
echo "Resultate für klaus von adder-2"
http :8092/results/klaus | jq .[].sum | uniq
+docker-compose kill -s 9 adder-2
+docker-compose start adder-1
docker-compose kill -s 9 peter klaus
+while ! [[ $(http 0:8091/actuator/health 2> /dev/null) =~ "UP" ]]; do echo "Waiting for adder-1..."; sleep 1; done
+until [ $(http --check-status :8091/results/peter 2> /dev/null) ]; do echo "Waiting for some results for peter to show up on adder-1..."; sleep 1; done
+until [ $(http --check-status :8091/results/klaus 2> /dev/null) ]; do echo "Waiting for some results for klaus to show up on adder-1..."; sleep 1; done
+
+echo "Resultate für adder-1"
+http -v --pretty none -S :8091/results
+echo
+
+echo "Resultate für peter von adder-1"
+http :8091/results/peter | jq .[].sum | uniq
+echo "Resultate für klaus von adder-1"
+http :8091/results/klaus | jq .[].sum | uniq
+
+sleep 5
+
+echo "Resultate für peter von adder-1"
+http :8091/results/peter | jq .[].sum | uniq
+echo "Resultate für klaus von adder-1"
+http :8091/results/klaus | jq .[].sum | uniq
stateRepository
.findById(Integer.toString(partition))
.orElse(new StateDocument(partition));
- recordHandler.addPartition(partition, document.state);
+ log.info(
+ "{} - Offset of next unseen message for partition {}: {}",
+ id,
+ partition,
+ document.offset);
+ recordHandler.addPartition(partition, document.state, document.offset);
for (String user : document.state.keySet())
{
log.info(
Integer partition = tp.partition();
log.info("{} - removing partition: {}", id, partition);
this.partitions.remove(partition);
- Map<String, AdderResult> state = recordHandler.removePartition(partition);
- for (String user : state.keySet())
+ ApplicationState state = recordHandler.removePartition(partition);
+ log.info(
+ "{} - offset of next unseen message for partition {} is {}",
+ id,
+ partition,
+ state.getOffset());
+ for (String user : state.getAdderState().keySet())
{
log.info(
"{} - Saved state for partition={}|user={}: {}",
id,
partition,
user,
- state.get(user));
+ state.getAdderState().get(user));
}
Map<String, List<AdderResult>> results = adderResults.removePartition(partition);
- stateRepository.save(new StateDocument(partition, state, results));
+ stateRepository.save(
+ new StateDocument(
+ partition,
+ state.getAdderState(),
+ results,
+ state.getOffset()));
});
}
}
private final String id;
private final Map<Integer, AdderBusinessLogic> state = new HashMap<>();
+ private final Map<Integer, Long> next = new HashMap<>();
@Override
String user = record.key();
String message = record.value();
+ if (record.offset() < next.get(partition))
+ {
+ log.warn(
+ "{}- Dropping duplicate message: offset={} < next={}",
+ id,
+ record.offset(),
+ next.get(partition));
+ return;
+ }
+
if (message.equals("CALCULATE"))
{
AdderResult result = state.get(partition).calculate(user);
state.get(partition).addToSum(user, Integer.parseInt(message));
}
+ next.put(partition, record.offset() + 1);
+
if (throttle.isPresent())
{
try
}
}
- protected void addPartition(Integer partition, Map<String, AdderResult> state)
+ protected void addPartition(Integer partition, Map<String, AdderResult> state, Long offset)
{
this.state.put(partition, new AdderBusinessLogic(state));
+ this.next.put(partition, offset);
}
- protected Map<String, AdderResult> removePartition(Integer partition)
+ protected ApplicationState removePartition(Integer partition)
{
- return this.state.remove(partition).getState();
+ ApplicationState state =
+ new ApplicationState(
+ this.next.get(partition),
+ this.state.remove(partition).getState());
+
+ this.next.remove(partition);
+
+ return state;
}
--- /dev/null
+package de.juplo.kafka;
+
+import lombok.Getter;
+import lombok.RequiredArgsConstructor;
+
+import java.util.Map;
+
+
+@RequiredArgsConstructor
+@Getter
+public class ApplicationState
+{
+ private final Long offset;
+ private final Map<String, AdderResult> adderState;
+}
{
@Id
public String id;
+ public long offset = 0l;
public Map<String, AdderResult> state;
public Map<String, List<AdderResult>> results;
public StateDocument(
Integer partition,
Map<String, AdderResult> state,
- Map<String, List<AdderResult>> results)
+ Map<String, List<AdderResult>> results,
+ long offset)
{
this.id = Integer.toString(partition);
this.state = state;
this.results = results;
+ this.offset = offset;
}
}