Skip to content

Commit 68a2c66

Browse files
committed
add code to reproduce behaviour (steve-community#1219)
1 parent d4503fe commit 68a2c66

File tree

2 files changed

+194
-2
lines changed

2 files changed

+194
-2
lines changed

src/main/java/de/rwth/idsg/steve/repository/impl/OcppServerRepositoryImpl.java

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -68,10 +68,11 @@
6868
*/
6969
@Slf4j
7070
@Repository
71+
@RequiredArgsConstructor
7172
public class OcppServerRepositoryImpl implements OcppServerRepository {
7273

73-
@Autowired private DSLContext ctx;
74-
@Autowired private ReservationRepository reservationRepository;
74+
private final DSLContext ctx;
75+
private final ReservationRepository reservationRepository;
7576

7677
private final Striped<Lock> transactionTableLocks = Striped.lock(16);
7778

Lines changed: 191 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,191 @@
1+
package de.rwth.idsg.steve.issues;
2+
3+
import de.rwth.idsg.steve.SteveException;
4+
import de.rwth.idsg.steve.repository.dto.InsertTransactionParams;
5+
import de.rwth.idsg.steve.repository.dto.OcppTag;
6+
import de.rwth.idsg.steve.repository.dto.Transaction;
7+
import de.rwth.idsg.steve.repository.dto.UpdateTransactionParams;
8+
import de.rwth.idsg.steve.repository.impl.AddressRepositoryImpl;
9+
import de.rwth.idsg.steve.repository.impl.ChargePointRepositoryImpl;
10+
import de.rwth.idsg.steve.repository.impl.OcppServerRepositoryImpl;
11+
import de.rwth.idsg.steve.repository.impl.OcppTagRepositoryImpl;
12+
import de.rwth.idsg.steve.repository.impl.ReservationRepositoryImpl;
13+
import de.rwth.idsg.steve.repository.impl.TransactionRepositoryImpl;
14+
import de.rwth.idsg.steve.web.dto.OcppTagForm;
15+
import de.rwth.idsg.steve.web.dto.OcppTagQueryForm;
16+
import de.rwth.idsg.steve.web.dto.TransactionQueryForm;
17+
import jooq.steve.db.enums.TransactionStopEventActor;
18+
import lombok.RequiredArgsConstructor;
19+
import org.joda.time.DateTime;
20+
import org.joda.time.Duration;
21+
import org.joda.time.LocalDateTime;
22+
import org.jooq.DSLContext;
23+
import org.jooq.SQLDialect;
24+
import org.jooq.impl.DSL;
25+
import org.jooq.impl.DataSourceConnectionProvider;
26+
import org.jooq.impl.DefaultConfiguration;
27+
import org.jooq.tools.jdbc.SingleConnectionDataSource;
28+
29+
import java.sql.Connection;
30+
import java.sql.DriverManager;
31+
import java.util.ArrayList;
32+
import java.util.List;
33+
import java.util.Objects;
34+
import java.util.UUID;
35+
import java.util.concurrent.ThreadLocalRandom;
36+
import java.util.stream.Collectors;
37+
import java.util.stream.IntStream;
38+
39+
@RequiredArgsConstructor
40+
public class Issue1219 {
41+
42+
private static final String url = "jdbc:mysql://localhost:3306/stevedb";
43+
private static final String userName = "steve";
44+
private static final String password = "changeme";
45+
46+
private final DSLContext ctx;
47+
48+
public static void main(String[] args) throws Exception {
49+
Connection con = DriverManager.getConnection(url, userName, password);
50+
51+
org.jooq.Configuration conf = new DefaultConfiguration()
52+
.set(SQLDialect.MYSQL)
53+
.set(new DataSourceConnectionProvider(new SingleConnectionDataSource(con)));
54+
55+
DSLContext ctx = DSL.using(conf);
56+
57+
Issue1219 issue1219 = new Issue1219(ctx);
58+
59+
var ocppTags = issue1219.insertOcppTags(1_000);
60+
System.out.println("inserted ocppTags");
61+
62+
var chargeBoxIds = issue1219.insertChargeBoxes(500);
63+
System.out.println("inserted chargeBoxIds");
64+
65+
var transactionIds = issue1219.insertStartTransactions(10_000, ocppTags, chargeBoxIds);
66+
System.out.println("inserted transaction_starts");
67+
68+
var stoppedTransactionIds = issue1219.insertStopTransactions(transactionIds);
69+
System.out.println("inserted transaction_stops: " + stoppedTransactionIds.size());
70+
71+
System.out.println("-- TESTING --");
72+
issue1219.realTest();
73+
}
74+
75+
private void realTest() {
76+
var repository = new OcppTagRepositoryImpl(ctx);
77+
78+
long start = System.currentTimeMillis();
79+
List<OcppTag.Overview> values = repository.getOverview(new OcppTagQueryForm());
80+
long stop = System.currentTimeMillis();
81+
82+
System.out.println("took " + Duration.millis(stop - start));
83+
}
84+
85+
private List<Integer> insertStopTransactions(List<Integer> insertedTransactionIds) {
86+
var ocppServerRepository = new OcppServerRepositoryImpl(ctx, new ReservationRepositoryImpl(ctx));
87+
var transactionRepository = new TransactionRepositoryImpl(ctx);
88+
89+
List<Integer> stopped = new ArrayList<>();
90+
for (Integer transactionId : insertedTransactionIds) {
91+
if (!ThreadLocalRandom.current().nextBoolean()) {
92+
continue;
93+
}
94+
95+
TransactionQueryForm form = new TransactionQueryForm();
96+
form.setTransactionPk(transactionId);
97+
Transaction transaction = transactionRepository.getTransactions(form).get(0);
98+
99+
DateTime stopTimestamp = transaction.getStartTimestamp().plusHours(1);
100+
UpdateTransactionParams p = UpdateTransactionParams.builder()
101+
.chargeBoxId(transaction.getChargeBoxId())
102+
.transactionId(transaction.getId())
103+
.stopTimestamp(stopTimestamp)
104+
.eventTimestamp(stopTimestamp)
105+
.stopMeterValue(transaction.getStartValue() + "0")
106+
.eventActor(TransactionStopEventActor.station)
107+
.build();
108+
109+
ocppServerRepository.updateTransaction(p);
110+
System.out.println("stopped transaction " + transactionId);
111+
stopped.add(transactionId);
112+
}
113+
return stopped;
114+
}
115+
116+
private List<Integer> insertStartTransactions(int count, List<String> ocppTags, List<String> chargeBoxIds) {
117+
var repository = new OcppServerRepositoryImpl(ctx, new ReservationRepositoryImpl(ctx));
118+
119+
List<Integer> transactionIds = new ArrayList<>();
120+
for (int i = 0; i < count; i++) {
121+
DateTime now = DateTime.now();
122+
InsertTransactionParams params = InsertTransactionParams.builder()
123+
.idTag(ocppTags.get(ThreadLocalRandom.current().nextInt(0, ocppTags.size())))
124+
.chargeBoxId(chargeBoxIds.get(ThreadLocalRandom.current().nextInt(0, chargeBoxIds.size())))
125+
.connectorId(ThreadLocalRandom.current().nextInt(4))
126+
.startMeterValue(String.valueOf(ThreadLocalRandom.current().nextLong(5_000, 20_000)))
127+
.startTimestamp(now)
128+
.eventTimestamp(now)
129+
.build();
130+
int transactionId = repository.insertTransaction(params);
131+
System.out.println("started transaction " + transactionId);
132+
transactionIds.add(transactionId);
133+
}
134+
return transactionIds;
135+
}
136+
137+
private List<String> insertChargeBoxes(int count) {
138+
var repository = new ChargePointRepositoryImpl(ctx, new AddressRepositoryImpl());
139+
140+
List<String> ids = IntStream.range(0, count).mapToObj(val -> UUID.randomUUID().toString()).collect(Collectors.toList());
141+
repository.addChargePointList(ids);
142+
143+
return ids;
144+
}
145+
146+
private List<String> insertOcppTags(int count) {
147+
var repository = new OcppTagRepositoryImpl(ctx);
148+
149+
List<String> idTags = IntStream.range(0, count).mapToObj(val -> UUID.randomUUID().toString()).collect(Collectors.toList());
150+
List<String> insertedTags = new ArrayList<>();
151+
152+
for (String idTag : idTags) {
153+
OcppTagForm form = new OcppTagForm();
154+
form.setIdTag(idTag);
155+
form.setExpiryDate(getRandomExpiry());
156+
form.setParentIdTag(getRandomParentIdTag(idTag, insertedTags));
157+
form.setMaxActiveTransactionCount(ThreadLocalRandom.current().nextInt(1, 4));
158+
159+
try {
160+
repository.addOcppTag(form);
161+
} catch (SteveException.AlreadyExists e) {
162+
// because the referenced idTag was not inserted yet. just inserted without it.
163+
form.setParentIdTag(null);
164+
repository.addOcppTag(form);
165+
}
166+
insertedTags.add(idTag);
167+
}
168+
169+
return insertedTags;
170+
}
171+
172+
private static String getRandomParentIdTag(String current, List<String> source) {
173+
if (source.isEmpty()) {
174+
return null;
175+
}
176+
if (ThreadLocalRandom.current().nextBoolean()) {
177+
String parent = source.get(ThreadLocalRandom.current().nextInt(0, source.size()));
178+
if (!Objects.equals(parent, current)) {
179+
return parent;
180+
}
181+
}
182+
return null;
183+
}
184+
185+
private static LocalDateTime getRandomExpiry() {
186+
if (ThreadLocalRandom.current().nextBoolean()) {
187+
return LocalDateTime.now().plusDays(ThreadLocalRandom.current().nextInt(1, 365));
188+
}
189+
return null;
190+
}
191+
}

0 commit comments

Comments
 (0)