Skip to content

Commit 8433d0f

Browse files
Merge 25.11 to 26.2
2 parents b427820 + a0363d2 commit 8433d0f

File tree

13 files changed

+556
-46
lines changed

13 files changed

+556
-46
lines changed

panoramapublic/src/org/labkey/panoramapublic/speclib/LibSourceFile.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package org.labkey.panoramapublic.speclib;
22

33
import org.apache.commons.io.FilenameUtils;
4+
import org.apache.commons.lang3.StringUtils;
45
import org.jetbrains.annotations.Nullable;
56

67
import java.util.List;
@@ -32,7 +33,7 @@ public boolean hasSpectrumSourceFile()
3233

3334
public boolean hasIdFile()
3435
{
35-
return idFile != null;
36+
return StringUtils.isNotBlank(idFile);
3637
}
3738

3839
public @Nullable String getIdFile()

testresults/src/org/labkey/testresults/TestResultsController.java

Lines changed: 160 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -111,6 +111,8 @@
111111
import java.util.Date;
112112
import java.util.Enumeration;
113113
import java.util.HashMap;
114+
import java.util.HashSet;
115+
import java.util.Set;
114116
import java.util.List;
115117
import java.util.Locale;
116118
import java.util.Map;
@@ -133,6 +135,60 @@ public class TestResultsController extends SpringActionController
133135

134136
private static final DefaultActionResolver _actionResolver = new DefaultActionResolver(TestResultsController.class);
135137

138+
// Tab name constants for menu highlighting
139+
public static class TabNames
140+
{
141+
// Request attribute name
142+
public static final String ACTIVE_TAB_ATTR = "activeTab";
143+
// CSS classes
144+
private static final String NAV_TAB_CLASS = "nav-tab";
145+
private static final String ACTIVE_CSS_CLASS = " active";
146+
147+
// Tab identifiers
148+
public static final String OVERVIEW = "overview";
149+
public static final String USER = "user";
150+
public static final String RUN = "run";
151+
public static final String LONGTERM = "longterm";
152+
public static final String FLAGS = "flags";
153+
public static final String TRAINING_DATA = "trainingdata";
154+
public static final String ERRORS = "errors";
155+
156+
/** Returns CSS class for a tab link: "nav-tab" or "nav-tab active" */
157+
public static String getTabClass(String tabName, String activeTab)
158+
{
159+
return NAV_TAB_CLASS + (tabName.equals(activeTab) ? ACTIVE_CSS_CLASS : "");
160+
}
161+
}
162+
163+
// Form class for RetrainAllAction
164+
public static class RetrainAllForm
165+
{
166+
private String _mode = "reset";
167+
private int _maxRuns = 20;
168+
private int _minRuns = 5;
169+
private Integer _targetRuns; // backwards compatibility
170+
171+
public String getMode() { return _mode; }
172+
public void setMode(String mode) { _mode = mode; }
173+
174+
public int getMaxRuns()
175+
{
176+
// Support legacy targetRuns parameter
177+
if (_targetRuns != null)
178+
return _targetRuns;
179+
return _maxRuns;
180+
}
181+
public void setMaxRuns(int maxRuns) { _maxRuns = maxRuns; }
182+
183+
public int getMinRuns() { return _minRuns; }
184+
public void setMinRuns(int minRuns) { _minRuns = minRuns; }
185+
186+
public Integer getTargetRuns() { return _targetRuns; }
187+
public void setTargetRuns(Integer targetRuns) { _targetRuns = targetRuns; }
188+
189+
public boolean isIncremental() { return "incremental".equalsIgnoreCase(_mode); }
190+
}
191+
136192
public TestResultsController()
137193
{
138194
setActionResolver(_actionResolver);
@@ -1037,6 +1093,110 @@ public Object execute(Object o, BindException errors)
10371093
}
10381094
}
10391095

1096+
@RequiresSiteAdmin
1097+
public static class RetrainAllAction extends MutatingApiAction<RetrainAllForm>
1098+
{
1099+
@Override
1100+
public Object execute(RetrainAllForm form, BindException errors)
1101+
{
1102+
// Validate and clamp parameters
1103+
int maxRuns = Math.max(1, Math.min(100, form.getMaxRuns()));
1104+
int minRuns = Math.max(1, Math.min(maxRuns, form.getMinRuns()));
1105+
boolean incremental = form.isIncremental();
1106+
1107+
Container c = getContainer();
1108+
String containerPath = c.getPath();
1109+
int expectedDuration = containerPath.toLowerCase().contains("perf") ? 720 : 540;
1110+
1111+
// Only look back 1.5x maxRuns days to avoid ancient data
1112+
int lookbackDays = (int) Math.ceil(maxRuns * 1.5);
1113+
java.sql.Timestamp cutoffDate = new java.sql.Timestamp(
1114+
System.currentTimeMillis() - (long) lookbackDays * 24 * 60 * 60 * 1000);
1115+
1116+
TestResultsManager mgr = TestResultsManager.get();
1117+
DbScope scope = TestResultsSchema.getSchema().getScope();
1118+
1119+
try (DbScope.Transaction transaction = scope.ensureTransaction())
1120+
{
1121+
List<Integer> allUserIds = mgr.getRecentUserIds(c, cutoffDate);
1122+
1123+
if (!incremental)
1124+
{
1125+
mgr.deleteTrainRunsForContainer(c);
1126+
mgr.deleteUserDataForContainer(c);
1127+
}
1128+
1129+
int usersRetrained = 0;
1130+
int totalTrainRuns = 0;
1131+
1132+
for (int userId : allUserIds)
1133+
{
1134+
Set<Integer> existingRunIds = mgr.getExistingTrainRunIds(userId, c);
1135+
List<Integer> recentCleanRunIds = mgr.getCleanRunIds(userId, c, cutoffDate, expectedDuration);
1136+
1137+
// Determine final set of trainrun IDs
1138+
List<Integer> finalRunIds;
1139+
if (incremental && !existingRunIds.isEmpty())
1140+
{
1141+
finalRunIds = mgr.getCandidateRunIds(userId, c, existingRunIds, recentCleanRunIds, maxRuns);
1142+
}
1143+
else
1144+
{
1145+
finalRunIds = recentCleanRunIds.size() > maxRuns
1146+
? new ArrayList<>(recentCleanRunIds.subList(0, maxRuns))
1147+
: new ArrayList<>(recentCleanRunIds);
1148+
}
1149+
1150+
// Skip if total runs is below minimum threshold
1151+
if (finalRunIds.size() < minRuns)
1152+
continue;
1153+
1154+
// Determine runs to add and remove
1155+
Set<Integer> finalRunSet = new HashSet<>(finalRunIds);
1156+
List<Integer> runsToAdd = new ArrayList<>();
1157+
List<Integer> runsToRemove = new ArrayList<>();
1158+
1159+
for (int runId : finalRunIds)
1160+
{
1161+
if (!existingRunIds.contains(runId))
1162+
runsToAdd.add(runId);
1163+
}
1164+
for (int runId : existingRunIds)
1165+
{
1166+
if (!finalRunSet.contains(runId))
1167+
runsToRemove.add(runId);
1168+
}
1169+
1170+
mgr.removeTrainRuns(runsToRemove);
1171+
mgr.addTrainRuns(runsToAdd);
1172+
1173+
boolean isActive = finalRunIds.size() >= maxRuns;
1174+
mgr.upsertUserData(userId, c, finalRunIds, isActive);
1175+
1176+
usersRetrained++;
1177+
totalTrainRuns += runsToAdd.size();
1178+
}
1179+
1180+
transaction.commit();
1181+
1182+
ApiSimpleResponse response = new ApiSimpleResponse();
1183+
response.put("success", true);
1184+
response.put("usersRetrained", usersRetrained);
1185+
response.put("totalTrainRuns", totalTrainRuns);
1186+
response.put("mode", form.getMode());
1187+
return response;
1188+
}
1189+
catch (Exception e)
1190+
{
1191+
_log.error("Error in RetrainAllAction", e);
1192+
ApiSimpleResponse response = new ApiSimpleResponse();
1193+
response.put("success", false);
1194+
response.put("error", e.getMessage());
1195+
return response;
1196+
}
1197+
}
1198+
}
1199+
10401200
/**
10411201
* action for posting test output as an xml file
10421202
*/

0 commit comments

Comments
 (0)