1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30 package co.stateful.core;
31
32 import co.stateful.spi.Counter;
33 import co.stateful.spi.Counters;
34 import com.amazonaws.services.dynamodbv2.model.AttributeValue;
35 import com.google.common.base.Function;
36 import com.google.common.base.Predicates;
37 import com.google.common.collect.Iterables;
38 import com.google.common.collect.Iterators;
39 import com.jcabi.aspects.Cacheable;
40 import com.jcabi.aspects.Immutable;
41 import com.jcabi.aspects.Loggable;
42 import com.jcabi.dynamo.Attributes;
43 import com.jcabi.dynamo.Conditions;
44 import com.jcabi.dynamo.Item;
45 import com.jcabi.dynamo.QueryValve;
46 import com.jcabi.dynamo.Table;
47 import com.jcabi.urn.URN;
48 import java.io.IOException;
49 import java.util.concurrent.TimeUnit;
50 import lombok.EqualsAndHashCode;
51 import lombok.ToString;
52
53
54
55
56
57
58
59 @Immutable
60 @ToString
61 @EqualsAndHashCode(of = "owner")
62 @Loggable(Loggable.DEBUG)
63 final class DyCounters implements Counters {
64
65
66
67
68 public static final String TBL = "counters";
69
70
71
72
73 public static final String HASH = "urn";
74
75
76
77
78 public static final String RANGE = "name";
79
80
81
82
83 public static final String ATTR_VALUE = "value";
84
85
86
87
88 private final transient Table table;
89
90
91
92
93 private final transient URN owner;
94
95
96
97
98
99
100 DyCounters(final Table tbl, final URN urn) {
101 this.table = tbl;
102 this.owner = urn;
103 }
104
105 @Override
106 @Cacheable.FlushAfter
107 public void create(final String name) throws IOException {
108 this.table.put(
109 new Attributes()
110 .with(DyCounters.HASH, this.owner)
111 .with(DyCounters.RANGE, name)
112 .with(DyCounters.ATTR_VALUE, new AttributeValue().withN("0"))
113 );
114 }
115
116 @Override
117 @Cacheable.FlushAfter
118 public void delete(final String name) {
119 Iterators.removeIf(
120 this.table.frame()
121 .through(new QueryValve().withLimit(1))
122 .where(DyCounters.HASH, Conditions.equalTo(this.owner))
123 .where(DyCounters.RANGE, Conditions.equalTo(name))
124 .iterator(),
125 Predicates.alwaysTrue()
126 );
127 }
128
129 @Override
130 @Cacheable(lifetime = 1, unit = TimeUnit.HOURS)
131 public Counter get(final String name) {
132 return new DyCounter(
133 this.table.frame()
134 .through(new QueryValve().withLimit(1))
135 .where(DyCounters.HASH, Conditions.equalTo(this.owner))
136 .where(DyCounters.RANGE, Conditions.equalTo(name))
137 .iterator()
138 .next()
139 );
140 }
141
142 @Override
143 @Cacheable(lifetime = 1, unit = TimeUnit.HOURS)
144 public Iterable<String> names() {
145 return Iterables.transform(
146 this.table.frame()
147 .through(new QueryValve())
148 .where(DyCounters.HASH, Conditions.equalTo(this.owner)),
149 new Function<Item, String>() {
150 @Override
151 public String apply(final Item item) {
152 try {
153 return item.get(DyCounters.RANGE).getS();
154 } catch (final IOException ex) {
155 throw new IllegalStateException(ex);
156 }
157 }
158 }
159 );
160 }
161 }