assertThat(value.entries().read(), Matchers.emptyIterable()); value.put("A", 1); value.put("B", 2); value.put("A", 11); assertThat(value.putIfAbsent("B", 22).read(), equalTo(2)); assertThat( value.entries().read(), containsInAnyOrder(MapEntry.of("A", 11), MapEntry.of("B", 2))); value.remove("A"); assertThat(value.entries().read(), containsInAnyOrder(MapEntry.of("B", 2))); value.remove("C"); assertThat(value.entries().read(), containsInAnyOrder(MapEntry.of("B", 2))); assertNull(value.get("A").read()); assertThat(value.get("B").read(), equalTo(2)); value.put("C", 3); value.put("D", 4); assertThat(value.get("C").read(), equalTo(3)); value.put("E", 5); value.remove("C"); assertThat(value.keys().read(), containsInAnyOrder("B", "D", "E")); assertThat(value.values().read(), containsInAnyOrder(2, 4, 5)); assertThat( value.entries().read(), containsInAnyOrder(MapEntry.of("B", 2), MapEntry.of("D", 4), MapEntry.of("E", 5))); assertThat(value.get("B").readLater().read(), equalTo(2)); assertNull(value.get("A").readLater().read());
@Test public void testMapReadable() throws Exception { MapState<String, Integer> value = underTest.state(NAMESPACE_1, STRING_MAP_ADDR); // test iterable, should just return a iterable view of the values contained in this map. // The iterable is backed by the map, so changes to the map are reflected in the iterable. ReadableState<Iterable<String>> keys = value.keys(); ReadableState<Iterable<Integer>> values = value.values(); ReadableState<Iterable<Map.Entry<String, Integer>>> entries = value.entries(); value.put("A", 1); assertFalse(Iterables.isEmpty(keys.read())); assertFalse(Iterables.isEmpty(values.read())); assertFalse(Iterables.isEmpty(entries.read())); // test get ReadableState<Integer> get = value.get("B"); value.put("B", 2); assertNull(get.read()); // test addIfAbsent value.putIfAbsent("C", 3); assertThat(value.get("C").read(), equalTo(3)); }
@Test public void testMapStateWithUnderlying() { CopyOnAccessInMemoryStateInternals<String> underlying = CopyOnAccessInMemoryStateInternals.withUnderlying(key, null); StateNamespace namespace = new StateNamespaceForTest("foo"); StateTag<MapState<String, Integer>> valueTag = StateTags.map("foo", StringUtf8Coder.of(), VarIntCoder.of()); MapState<String, Integer> underlyingValue = underlying.state(namespace, valueTag); assertThat(underlyingValue.entries().read(), emptyIterable()); underlyingValue.put("hello", 1); assertThat(underlyingValue.get("hello").read(), equalTo(1)); CopyOnAccessInMemoryStateInternals<String> internals = CopyOnAccessInMemoryStateInternals.withUnderlying(key, underlying); MapState<String, Integer> copyOnAccessState = internals.state(namespace, valueTag); assertThat(copyOnAccessState.get("hello").read(), equalTo(1)); copyOnAccessState.put("world", 4); assertThat(copyOnAccessState.get("hello").read(), equalTo(1)); assertThat(copyOnAccessState.get("world").read(), equalTo(4)); assertThat(underlyingValue.get("hello").read(), equalTo(1)); assertNull(underlyingValue.get("world").read()); MapState<String, Integer> reReadUnderlyingValue = underlying.state(namespace, valueTag); assertThat(underlyingValue.entries().read(), equalTo(reReadUnderlyingValue.entries().read())); }
@ProcessElement public void processElement( ProcessContext c, @Element KV<String, KV<String, Integer>> element, @StateId(stateId) MapState<String, Integer> state, @StateId(countStateId) CombiningState<Integer, int[], Integer> count, OutputReceiver<KV<String, Integer>> r) { KV<String, Integer> value = element.getValue(); ReadableState<Iterable<Entry<String, Integer>>> entriesView = state.entries(); state.put(value.getKey(), value.getValue()); count.add(1); if (count.read() >= 4) { Iterable<Map.Entry<String, Integer>> iterate = state.entries().read(); // Make sure that the cached Iterable doesn't change when new elements are added, // but that cached ReadableState views of the state do change. state.put("BadKey", -1); assertEquals(3, Iterables.size(iterate)); assertEquals(4, Iterables.size(entriesView.read())); assertEquals(4, Iterables.size(state.entries().read())); for (Map.Entry<String, Integer> entry : iterate) { r.output(KV.of(entry.getKey(), entry.getValue())); } } } };
if (!visit.isGoal()) { LOG.info("Adding visit: {}", visit); visitsState.put(visit.url(), visit); } else { LOG.info("Adding goal (if absent): {}", visit); impressionsState.putIfAbsent(impression.sourceAndTarget(), impression);
@Test public void testMapStateWithUnderlying() { CopyOnAccessInMemoryStateInternals<String> underlying = CopyOnAccessInMemoryStateInternals.withUnderlying(key, null); StateNamespace namespace = new StateNamespaceForTest("foo"); StateTag<MapState<String, Integer>> valueTag = StateTags.map("foo", StringUtf8Coder.of(), VarIntCoder.of()); MapState<String, Integer> underlyingValue = underlying.state(namespace, valueTag); assertThat(underlyingValue.entries().read(), emptyIterable()); underlyingValue.put("hello", 1); assertThat(underlyingValue.get("hello").read(), equalTo(1)); CopyOnAccessInMemoryStateInternals<String> internals = CopyOnAccessInMemoryStateInternals.withUnderlying(key, underlying); MapState<String, Integer> copyOnAccessState = internals.state(namespace, valueTag); assertThat(copyOnAccessState.get("hello").read(), equalTo(1)); copyOnAccessState.put("world", 4); assertThat(copyOnAccessState.get("hello").read(), equalTo(1)); assertThat(copyOnAccessState.get("world").read(), equalTo(4)); assertThat(underlyingValue.get("hello").read(), equalTo(1)); assertNull(underlyingValue.get("world").read()); MapState<String, Integer> reReadUnderlyingValue = underlying.state(namespace, valueTag); assertThat(underlyingValue.entries().read(), equalTo(reReadUnderlyingValue.entries().read())); }
@ProcessElement public void processElement( @Element KV<String, KV<String, Integer>> element, @StateId(stateId) MapState<String, MyInteger> state, @StateId(countStateId) CombiningState<Integer, int[], Integer> count, OutputReceiver<KV<String, MyInteger>> r) { KV<String, Integer> value = element.getValue(); state.put(value.getKey(), new MyInteger(value.getValue())); count.add(1); if (count.read() >= 4) { Iterable<Map.Entry<String, MyInteger>> iterate = state.entries().read(); for (Map.Entry<String, MyInteger> entry : iterate) { r.output(KV.of(entry.getKey(), entry.getValue())); } } } };
@ProcessElement public void processElement( ProcessContext c, @Element KV<String, KV<String, Integer>> element, @StateId(stateId) MapState<String, MyInteger> state, @StateId(countStateId) CombiningState<Integer, int[], Integer> count, OutputReceiver<KV<String, MyInteger>> r) { KV<String, Integer> value = element.getValue(); state.put(value.getKey(), new MyInteger(value.getValue())); count.add(1); if (count.read() >= 4) { Iterable<Map.Entry<String, MyInteger>> iterate = state.entries().read(); for (Map.Entry<String, MyInteger> entry : iterate) { r.output(KV.of(entry.getKey(), entry.getValue())); } } } };