Skip to content

Commit 4c7c92c

Browse files
committed
SEBSP-210 tested SESSION_SCREENSHOT_DATA_CACHE and recorder
1 parent c204f99 commit 4c7c92c

File tree

7 files changed

+30
-222
lines changed

7 files changed

+30
-222
lines changed

src/main/java/ch/ethz/seb/sps/server/datalayer/dao/ScreenshotDataDAO.java

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -30,18 +30,11 @@ public interface ScreenshotDataDAO extends EntityDAO<ScreenshotData, ScreenshotD
3030

3131
Result<Collection<ScreenshotDataRecord>> allOfSession(String sessionUUID);
3232

33-
//Result<ScreenshotDataRecord> getAt(String sessionUUID, Long at);
34-
35-
//Result<Long> getIdAt(String sessionUUID, Long at);
36-
37-
//Result<Long> getLatestImageId(String sessionUUID);
38-
3933
Result<Collection<Long>> getScreenshotTimestamps(String sessionUUID, Long timestamp, PageSortOrder sortOrder);
4034

4135
Result<ScreenshotDataRecord> getLatest(String sessionUUID);
4236

4337
Result<Map<String, ScreenshotDataRecord>> allOfMappedToSession(List<Long> pks);
44-
//Result<Map<String, ScreenshotDataRecord>> allLatestIn(List<String> sessionUUIDs);
4538

4639
Result<Long> save(
4740
String sessionId,

src/main/java/ch/ethz/seb/sps/server/datalayer/dao/SessionDAO.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
import java.util.Collection;
1313
import java.util.List;
1414
import java.util.Map;
15+
import java.util.Set;
1516

1617
import ch.ethz.seb.sps.domain.model.EntityKey;
1718
import ch.ethz.seb.sps.domain.model.FilterMap;

src/main/java/ch/ethz/seb/sps/server/datalayer/dao/impl/ScreenshotDataDAOBatis.java

Lines changed: 0 additions & 151 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,6 @@
1919
import java.util.Collections;
2020
import java.util.List;
2121
import java.util.Map;
22-
import java.util.Objects;
2322
import java.util.Set;
2423
import java.util.function.Function;
2524
import java.util.stream.Collectors;
@@ -120,119 +119,6 @@ public Result<Collection<ScreenshotDataRecord>> allOfSession(final String sessio
120119
.execute());
121120
}
122121

123-
// @Override
124-
// @Transactional(readOnly = true)
125-
// public Result<ScreenshotDataRecord> getAt(final String sessionUUID, final Long at) {
126-
//
127-
// System.out.print("******************** getAt called for session: " + sessionUUID + " with at: " + at);
128-
//
129-
// // TODO: this seems to produce performance issues when table is huge. Try to optimize query by reducing the time frame here
130-
// return Result.tryCatch(() -> {
131-
// ScreenshotDataRecord record = SelectDSL
132-
// .selectWithMapper(this.screenshotDataRecordMapper::selectOne,
133-
// id,
134-
// sessionUuid,
135-
// timestamp,
136-
// imageFormat,
137-
// metaData,
138-
// timestamp)
139-
// .from(screenshotDataRecord)
140-
// .where(ScreenshotDataRecordDynamicSqlSupport.sessionUuid, SqlBuilder.isEqualTo(sessionUUID))
141-
// .and(ScreenshotDataRecordDynamicSqlSupport.timestamp, SqlBuilder.isLessThanOrEqualTo(at))
142-
// .orderBy(timestamp.descending())
143-
// .limit(1)
144-
// .build()
145-
// .execute();
146-
//
147-
// if (record != null) {
148-
// return record;
149-
// }
150-
//
151-
// // there is no screenshot at the time of given timestamp. Try to get first image for the session
152-
// record = SelectDSL
153-
// .selectWithMapper(this.screenshotDataRecordMapper::selectOne,
154-
// id,
155-
// sessionUuid,
156-
// timestamp,
157-
// imageFormat,
158-
// metaData,
159-
// timestamp)
160-
// .from(screenshotDataRecord)
161-
// .where(ScreenshotDataRecordDynamicSqlSupport.sessionUuid, SqlBuilder.isEqualTo(sessionUUID))
162-
// .orderBy(timestamp)
163-
// .limit(1)
164-
// .build()
165-
// .execute();
166-
//
167-
// // still no screenshot... seems that there are none at this time
168-
// if (record == null) {
169-
// throw new NoResourceFoundException(EntityType.SCREENSHOT_DATA, sessionUUID);
170-
// }
171-
//
172-
// return record;
173-
// });
174-
// }
175-
176-
// @Override
177-
// @Transactional(readOnly = true)
178-
// public Result<Long> getIdAt(final String sessionUUID, final Long at) {
179-
// return Result.tryCatch(() -> {
180-
//
181-
// System.out.println("******************** getIdAt called for session: " + sessionUUID + " with at: " + at);
182-
//
183-
// List<Long> result = SelectDSL
184-
// .selectWithMapper(this.screenshotDataRecordMapper::selectIds, id, timestamp)
185-
// .from(screenshotDataRecord)
186-
// .where(ScreenshotDataRecordDynamicSqlSupport.sessionUuid, SqlBuilder.isEqualTo(sessionUUID))
187-
// .and(ScreenshotDataRecordDynamicSqlSupport.timestamp, SqlBuilder.isLessThanOrEqualTo(at))
188-
// .orderBy(timestamp.descending())
189-
// .limit(1)
190-
// .build()
191-
// .execute();
192-
//
193-
// if (result != null && !result.isEmpty()) {
194-
// return result.get(0);
195-
// }
196-
//
197-
// // there is no screenshot at the time of given timestamp. Try to get first image for the session
198-
// result = SelectDSL
199-
// .selectWithMapper(this.screenshotDataRecordMapper::selectIds, id, timestamp)
200-
// .from(screenshotDataRecord)
201-
// .where(ScreenshotDataRecordDynamicSqlSupport.sessionUuid, SqlBuilder.isEqualTo(sessionUUID))
202-
// .orderBy(timestamp)
203-
// .limit(1)
204-
// .build()
205-
// .execute();
206-
//
207-
// // still no screenshot... seems that there are none at this time
208-
// if (result == null || result.isEmpty()) {
209-
// throw new NoResourceFoundException(EntityType.SCREENSHOT_DATA, sessionUUID);
210-
// }
211-
//
212-
// return result.get(0);
213-
// });
214-
// }
215-
216-
// @Override
217-
// @Transactional(readOnly = true)
218-
// public Result<Long> getLatestImageId(final String sessionUUID) {
219-
// return Result.tryCatch(() -> {
220-
//
221-
// System.out.println("******************** getLatestImageId called for session: " + sessionUUID );
222-
//
223-
// final List<Long> execute = SelectDSL
224-
// .selectDistinctWithMapper(this.screenshotDataRecordMapper::selectIds, id, timestamp)
225-
// .from(screenshotDataRecord)
226-
// .where(ScreenshotDataRecordDynamicSqlSupport.sessionUuid, SqlBuilder.isEqualTo(sessionUUID))
227-
// .orderBy(timestamp.descending())
228-
// .limit(1)
229-
// .build()
230-
// .execute();
231-
//
232-
// return execute.get(0);
233-
// });
234-
// }
235-
236122
@Override
237123
@Transactional(readOnly = true)
238124
public Result<ScreenshotDataRecord> getLatest(final String sessionUUID) {
@@ -271,43 +157,6 @@ public Result<Map<String, ScreenshotDataRecord>> allOfMappedToSession(final List
271157
});
272158
}
273159

274-
// @Override
275-
// @Transactional(readOnly = true)
276-
// public Result<Map<String, ScreenshotDataRecord>> allLatestIn(final List<String> sessionUUIDs) {
277-
// return Result.tryCatch(() -> {
278-
// if (sessionUUIDs == null || sessionUUIDs.isEmpty()) {
279-
// return Collections.emptyMap();
280-
// }
281-
//
282-
// // NOTE: This was not working as expected since limit does not work with group (groupBy)
283-
//// return SelectDSL
284-
//// .selectWithMapper(this.screenshotDataRecordMapper::selectMany,
285-
//// id,
286-
//// sessionUuid,
287-
//// timestamp,
288-
//// imageFormat,
289-
//// metaData)
290-
//// .from(screenshotDataRecord)
291-
//// .where(ScreenshotDataRecordDynamicSqlSupport.sessionUuid, SqlBuilder.isIn(sessionUUIDs))
292-
//// .groupBy(ScreenshotDataRecordDynamicSqlSupport.sessionUuid)
293-
//// .orderBy(timestamp.descending())
294-
//// .limit(1)
295-
//// .build()
296-
//// .execute()
297-
//// .stream()
298-
//// .collect(Collectors.toMap(r -> r.getSessionUuid(), Function.identity()));
299-
//
300-
// // NOTE: For now we use a less efficient version that uses getLatest(final String sessionUUID) for
301-
// // all requested sessions but in the future we should solve this problem on DB layer
302-
// return sessionUUIDs.stream()
303-
// .map(this::getLatestScreenshotDataRec)
304-
// .filter(Objects::nonNull)
305-
// .collect(Collectors.toMap(
306-
// ScreenshotDataRecord::getSessionUuid,
307-
// Function.identity()));
308-
// });
309-
// }
310-
311160
@Override
312161
@Transactional(readOnly = true)
313162
public Result<Collection<ScreenshotData>> allMatching(

src/main/java/ch/ethz/seb/sps/server/servicelayer/impl/ProctoringCacheService.java

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -162,9 +162,13 @@ public SessionScreenshotCacheData getSessionScreenshotData(final String sessionU
162162
if (result.hasError()) {
163163
log.warn("Failed to get all screenshot data for session: {}", sessionUUID);
164164
return null;
165+
} else {
166+
Collection<ScreenshotDataRecord> screenshotDataRecords = result.get();
167+
if (log.isDebugEnabled()) {
168+
log.debug("Got SessionScreenshotCacheData for session: {} with {} entries", sessionUUID, screenshotDataRecords.size());
169+
}
170+
return new SessionScreenshotCacheData(sessionUUID, screenshotDataRecords);
165171
}
166-
167-
return new SessionScreenshotCacheData(sessionUUID, result.get());
168172
}
169173

170174
@CacheEvict(

src/main/java/ch/ethz/seb/sps/server/servicelayer/impl/ProctoringServiceImpl.java

Lines changed: 18 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88

99
package ch.ethz.seb.sps.server.servicelayer.impl;
1010

11+
import javax.cache.Cache;
1112
import java.io.InputStream;
1213
import java.io.OutputStream;
1314
import java.sql.Date;
@@ -21,8 +22,12 @@
2122
import ch.ethz.seb.sps.server.datalayer.dao.*;
2223
import ch.ethz.seb.sps.server.servicelayer.LiveProctoringCacheService;
2324
import org.apache.tomcat.util.http.fileupload.IOUtils;
25+
import org.ehcache.core.Ehcache;
2426
import org.slf4j.Logger;
2527
import org.slf4j.LoggerFactory;
28+
import org.springframework.boot.autoconfigure.cache.CacheProperties;
29+
import org.springframework.cache.CacheManager;
30+
import org.springframework.cache.jcache.JCacheCache;
2631
import org.springframework.context.annotation.Lazy;
2732
import org.springframework.stereotype.Component;
2833

@@ -59,6 +64,7 @@ public class ProctoringServiceImpl implements ProctoringService {
5964
private final UserService userService;
6065
private final ServiceInfo serviceInfo;
6166
private final JSONMapper jsonMapper;
67+
private final CacheManager cacheManager;
6268
private final boolean isDistributedSetup;
6369
private final long distributedUpdateInterval;
6470

@@ -68,11 +74,12 @@ public ProctoringServiceImpl(
6874
final SessionDAO sessionDAO,
6975
final ScreenshotDAO screenshotDAO,
7076
final ScreenshotDataDAO screenshotDataDAO,
71-
final ProctoringCacheService proctoringCacheService,
77+
final ProctoringCacheService proctoringCacheService,
7278
final LiveProctoringCacheService liveProctoringCacheService,
7379
final UserService userService,
7480
final ServiceInfo serviceInfo,
75-
final JSONMapper jsonMapper) {
81+
final JSONMapper jsonMapper,
82+
final CacheManager cacheManager) {
7683

7784
this.examDAO = examDAO;
7885
this.groupDAO = groupDAO;
@@ -86,7 +93,8 @@ public ProctoringServiceImpl(
8693
this.jsonMapper = jsonMapper;
8794
this.distributedUpdateInterval = serviceInfo.getDistributedUpdateInterval();
8895
this.isDistributedSetup = serviceInfo.isDistributed();
89-
}
96+
this.cacheManager = cacheManager;
97+
}
9098

9199
@Override
92100
public void checkMonitoringAccess(final String groupUUID) {
@@ -109,32 +117,18 @@ public void checkMonitoringSessionAccess(final String sessionUUID) {
109117
}
110118

111119
@Override
112-
public Result<ScreenshotViewData> getRecordedImageDataAt(final String sessionUUID, final Long timestamp) {
120+
public synchronized Result<ScreenshotViewData> getRecordedImageDataAt(final String sessionUUID, final Long timestamp) {
113121
return Result.tryCatch(() -> {
114-
if (timestamp != null) {
115-
116-
return createScreenshotViewData(
117-
sessionUUID,
118-
this.proctoringCacheService.getSessionScreenshotData(sessionUUID).getAt(timestamp));
119-
} else {
120-
Long latestSSDataId = this.liveProctoringCacheService.getLatestSSDataId(sessionUUID, true);
121-
if (latestSSDataId != null && latestSSDataId != -1L) {
122-
return screenshotDataDAO
123-
.recordByPK(latestSSDataId)
124-
.map(data -> createScreenshotViewData(sessionUUID, data))
125-
.getOrThrow();
126-
} else {
127-
if (log.isDebugEnabled()) {
128-
log.debug("No latest screenshot available yet for session: {}", sessionUUID);
129-
}
130-
throw new NoResourceFoundException(EntityType.SCREENSHOT_DATA, "No latest screenshot available yet");
131-
}
132-
}
122+
final SessionScreenshotCacheData sessionScreenshotData = this.proctoringCacheService
123+
.getSessionScreenshotData(sessionUUID);
124+
return createScreenshotViewData(
125+
sessionUUID,
126+
sessionScreenshotData.getAt(timestamp));
133127
});
134128
}
135129

136130
@Override
137-
public Result<ScreenshotsInGroupData> getSessionsByGroup(
131+
public synchronized Result<ScreenshotsInGroupData> getSessionsByGroup(
138132
final String groupUUID,
139133
final Integer pageNumber,
140134
final Integer pageSize,
@@ -429,11 +423,6 @@ private void streamLatestScreenshot(final String sessionUUID, final OutputStream
429423
screenshotIn = this.screenshotDAO
430424
.getImage(this.liveProctoringCacheService.getLatestSSDataId(sessionUUID, true), sessionUUID)
431425
.getOrThrow();
432-
//
433-
// screenshotIn = this.screenshotDataDAO
434-
// .getLatestImageId(sessionUUID)
435-
// .flatMap(pk -> this.screenshotDAO.getImage(pk, sessionUUID))
436-
// .getOrThrow();
437426

438427
IOUtils.copy(screenshotIn, out);
439428

@@ -469,11 +458,6 @@ private void streamScreenshotAt(
469458
.getImage(at.getId(), sessionUUID)
470459
.getOrThrow();
471460

472-
// screenshotIn = this.screenshotDataDAO
473-
// .getIdAt(sessionUUID, timestamp)
474-
// .flatMap(pk -> this.screenshotDAO.getImage(pk, sessionUUID))
475-
// .getOrThrow();
476-
477461
IOUtils.copy(screenshotIn, out);
478462
} catch (final Exception e) {
479463
if (e instanceof RuntimeException) {
@@ -627,7 +611,6 @@ private void updateSessionCache(String groupUUID) {
627611
this.clearGroupCache(groupUUID, true);
628612
} else {
629613

630-
// TODO use CacheManager to get all actual cached sessions to update
631614
Map<String, Long> updateTimes = this.proctoringCacheService
632615
.getLiveSessionTokens(activeGroup.uuid)
633616
.stream()

src/main/java/ch/ethz/seb/sps/server/servicelayer/impl/SessionScreenshotCacheData.java

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ public SessionScreenshotCacheData(
2525
final Collection<ScreenshotDataRecord> data) {
2626

2727
this.sessionUUID = sessionUUID;
28-
this.data = data.toArray(new ScreenshotDataRecord[data.size()]);
28+
this.data = data.toArray(new ScreenshotDataRecord[0]);
2929
Arrays.sort(
3030
this.data,
3131
Comparator.comparing(ScreenshotDataRecord::getTimestamp));
@@ -36,6 +36,10 @@ public SessionScreenshotCacheData(
3636
}
3737

3838
public ScreenshotDataRecord getAt(Long timestamp) {
39+
if (timestamp == null) {
40+
return data[0];
41+
}
42+
3943
final int i = Arrays.binarySearch(timestamps, timestamp);
4044
if (i >= 0) {
4145
return data[i];

0 commit comments

Comments
 (0)