2828import ch .ethz .seb .sps .server .datalayer .batis .custommappers .ScreenshotDataMapper ;
2929import ch .ethz .seb .sps .server .datalayer .batis .custommappers .SearchApplicationMapper ;
3030import ch .ethz .seb .sps .domain .model .service .UserListForApplicationSearch ;
31+ import ch .ethz .seb .sps .utils .Utils ;
3132import org .apache .commons .lang3 .StringUtils ;
3233import org .mybatis .dynamic .sql .SqlBuilder ;
3334import org .mybatis .dynamic .sql .select .MyBatis3SelectModelAdapter ;
@@ -126,88 +127,22 @@ public Result<Collection<ScreenshotData>> allOfSession(final String sessionUUID)
126127 @ Override
127128 @ Transactional (readOnly = true )
128129 public Result <ScreenshotDataRecord > getAt (final String sessionUUID , final Long at ) {
129- // TODO: this seems to produce performance issues when table is huge. Try to optimize query by reducing the time frame here
130130 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 ;
131+ return getScreenshotDataAt (sessionUUID , at );
173132 });
174133 }
175134
176135 @ Override
177136 @ Transactional (readOnly = true )
178137 public Result <Long > getIdAt (final String sessionUUID , final Long at ) {
179138 return Result .tryCatch (() -> {
180-
181- List <Long > result = SelectDSL
182- .selectWithMapper (this .screenshotDataRecordMapper ::selectIds , id , timestamp )
183- .from (screenshotDataRecord )
184- .where (ScreenshotDataRecordDynamicSqlSupport .sessionUuid , SqlBuilder .isEqualTo (sessionUUID ))
185- .and (ScreenshotDataRecordDynamicSqlSupport .timestamp , SqlBuilder .isLessThanOrEqualTo (at ))
186- .orderBy (timestamp .descending ())
187- .limit (1 )
188- .build ()
189- .execute ();
190-
191- if (result != null && !result .isEmpty ()) {
192- return result .get (0 );
193- }
194-
195- // there is no screenshot at the time of given timestamp. Try to get first image for the session
196- result = SelectDSL
197- .selectWithMapper (this .screenshotDataRecordMapper ::selectIds , id , timestamp )
198- .from (screenshotDataRecord )
199- .where (ScreenshotDataRecordDynamicSqlSupport .sessionUuid , SqlBuilder .isEqualTo (sessionUUID ))
200- .orderBy (timestamp )
201- .limit (1 )
202- .build ()
203- .execute ();
204-
205- // still no screenshot... seems that there are none at this time
206- if (result == null || result .isEmpty ()) {
207- throw new NoResourceFoundException (EntityType .SCREENSHOT_DATA , sessionUUID );
139+ ScreenshotDataRecord screenshotDataAt = getScreenshotDataAt (sessionUUID , at );
140+
141+ if (screenshotDataAt != null ) {
142+ return screenshotDataAt .getId ();
208143 }
209144
210- return result . get ( 0 );
145+ throw new NoResourceFoundException ( EntityType . SCREENSHOT_DATA , sessionUUID );
211146 });
212147 }
213148
@@ -216,24 +151,21 @@ public Result<Long> getIdAt(final String sessionUUID, final Long at) {
216151 public Result <Long > getLatestImageId (final String sessionUUID ) {
217152 return Result .tryCatch (() -> {
218153
219- final List <Long > execute = SelectDSL
220- .selectDistinctWithMapper (this .screenshotDataRecordMapper ::selectIds , id , timestamp )
221- .from (screenshotDataRecord )
222- .where (ScreenshotDataRecordDynamicSqlSupport .sessionUuid , SqlBuilder .isEqualTo (sessionUUID ))
223- .orderBy (timestamp .descending ())
224- .limit (1 )
225- .build ()
226- .execute ();
154+ ScreenshotDataRecord screenshotDataAt = getScreenshotDataAt (sessionUUID , null );
155+ if (screenshotDataAt != null ) {
156+ return screenshotDataAt .getId ();
157+ }
227158
228- return execute . get ( 0 );
159+ throw new NoResourceFoundException ( EntityType . SCREENSHOT_DATA , sessionUUID );
229160 });
230161 }
231162
232163 @ Override
233164 @ Transactional (readOnly = true )
234165 public Result <ScreenshotDataRecord > getLatest (final String sessionUUID ) {
235166 return Result .tryCatch (() -> {
236- final ScreenshotDataRecord latestScreenshotDataRec = getLatestScreenshotDataRec (sessionUUID );
167+
168+ final ScreenshotDataRecord latestScreenshotDataRec = getScreenshotDataAt (sessionUUID , null );
237169 if (latestScreenshotDataRec == null ) {
238170 throw new NoResourceFoundException (EntityType .SCREENSHOT_DATA , sessionUUID );
239171 }
@@ -249,28 +181,10 @@ public Result<Map<String, ScreenshotDataRecord>> allLatestIn(final List<String>
249181 return Collections .emptyMap ();
250182 }
251183
252- // NOTE: This was not working as expected since limit does not work with group (groupBy)
253- // return SelectDSL
254- // .selectWithMapper(this.screenshotDataRecordMapper::selectMany,
255- // id,
256- // sessionUuid,
257- // timestamp,
258- // imageFormat,
259- // metaData)
260- // .from(screenshotDataRecord)
261- // .where(ScreenshotDataRecordDynamicSqlSupport.sessionUuid, SqlBuilder.isIn(sessionUUIDs))
262- // .groupBy(ScreenshotDataRecordDynamicSqlSupport.sessionUuid)
263- // .orderBy(timestamp.descending())
264- // .limit(1)
265- // .build()
266- // .execute()
267- // .stream()
268- // .collect(Collectors.toMap(r -> r.getSessionUuid(), Function.identity()));
269-
270184 // NOTE: For now we use a less efficient version that uses getLatest(final String sessionUUID) for
271185 // all requested sessions but in the future we should solve this problem on DB layer
272186 return sessionUUIDs .stream ()
273- .map (this :: getLatestScreenshotDataRec )
187+ .map (sessionUUID -> getScreenshotDataAt ( sessionUUID , null ) )
274188 .filter (Objects ::nonNull )
275189 .collect (Collectors .toMap (
276190 ScreenshotDataRecord ::getSessionUuid ,
@@ -746,4 +660,59 @@ private String createMetadataSearchString(String metadataKey, String metadataVal
746660 Constants .PERCENTAGE_STRING ;
747661 }
748662
663+ private ScreenshotDataRecord getScreenshotDataAt (final String sessionUUID , final Long at ) {
664+ final Long ts = at != null ? at : Utils .getMillisecondsNow ();
665+
666+ ScreenshotDataRecord record = getLastScreenshotDataRecordInRange (sessionUUID , ts , ts - 30 * Constants .SECOND_IN_MILLIS );
667+ if (record != null ) {
668+ return record ;
669+ }
670+
671+ if (log .isDebugEnabled ()) {
672+ log .debug ("Did not find screenshot within 30s interval, try 1 hour interval" );
673+ }
674+
675+ record = getLastScreenshotDataRecordInRange (sessionUUID , ts , ts - Constants .HOUR_IN_MILLIS );
676+ if (record != null ) {
677+ return record ;
678+ }
679+
680+ if (log .isDebugEnabled ()) {
681+ log .debug ("Did not find screenshot within 1 hour interval, get first image: {}" , sessionUUID );
682+ }
683+
684+ return SelectDSL
685+ .selectWithMapper (this .screenshotDataRecordMapper ::selectOne ,
686+ id ,
687+ sessionUuid ,
688+ timestamp ,
689+ imageFormat ,
690+ metaData ,
691+ timestamp )
692+ .from (screenshotDataRecord )
693+ .where (ScreenshotDataRecordDynamicSqlSupport .sessionUuid , SqlBuilder .isEqualTo (sessionUUID ))
694+ .limit (1 )
695+ .build ()
696+ .execute ();
697+ }
698+
699+ private ScreenshotDataRecord getLastScreenshotDataRecordInRange (final String sessionUUID , final Long upper , final Long lower ) {
700+ return SelectDSL
701+ .selectWithMapper (this .screenshotDataRecordMapper ::selectOne ,
702+ id ,
703+ sessionUuid ,
704+ timestamp ,
705+ imageFormat ,
706+ metaData ,
707+ timestamp )
708+ .from (screenshotDataRecord )
709+ .where (ScreenshotDataRecordDynamicSqlSupport .sessionUuid , SqlBuilder .isEqualTo (sessionUUID ))
710+ .and (ScreenshotDataRecordDynamicSqlSupport .timestamp , SqlBuilder .isLessThan (upper ))
711+ .and (ScreenshotDataRecordDynamicSqlSupport .timestamp , SqlBuilder .isGreaterThanOrEqualToWhenPresent (lower ))
712+ .orderBy (timestamp .descending ())
713+ .limit (1 )
714+ .build ()
715+ .execute ();
716+ }
717+
749718}
0 commit comments