Skip to content

Commit

Permalink
Merge pull request #1415 from virtualcell/user-query-cli
Browse files Browse the repository at this point in the history
new users-query CLI command lists users who ran sim since a start date
  • Loading branch information
jcschaff authored Jan 13, 2025
2 parents 654e1cb + 2f3cd10 commit 3e40e24
Show file tree
Hide file tree
Showing 4 changed files with 140 additions and 8 deletions.
2 changes: 2 additions & 0 deletions vcell-admin/src/main/java/org/vcell/admin/cli/AdminCLI.java
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
import org.vcell.admin.cli.sim.ResultSetCrawlerCommand;
import org.vcell.admin.cli.sim.SimDataVerifierCommand;
import org.vcell.admin.cli.tools.UsageCommand;
import org.vcell.admin.cli.tools.UsersQueryCommand;
import org.vcell.db.DatabaseSyntax;
import org.vcell.dependency.server.VCellServerModule;
import org.vcell.util.document.KeyValue;
Expand All @@ -31,6 +32,7 @@
DatabaseDestroyAndRecreateCommand.class,
DatabaseCreateScriptCommand.class,
UsageCommand.class,
UsersQueryCommand.class,
ResultSetCrawlerCommand.class,
SimDataVerifierCommand.class,
JobInfoCommand.class,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@
import cbit.vcell.message.server.dispatcher.SimulationDatabaseDirect;
import cbit.vcell.modeldb.*;
import cbit.vcell.server.SimulationJobStatusPersistent;
import cbit.vcell.xml.XmlParseException;
import org.vcell.admin.cli.sim.JobAdmin;
import org.vcell.admin.cli.sim.ResultSetCrawler;
import org.vcell.admin.cli.sim.SimDataVerifier;
Expand Down Expand Up @@ -93,6 +92,11 @@ public String getBasicStatistics() throws SQLException, DataAccessException {
return adminDbTopLevel.getBasicStatistics();
}

public AdminDBTopLevel.DbUserSimCount[] getUserSimCount(int pastTime_days) throws SQLException, DataAccessException {
AdminDBTopLevel adminDbTopLevel = new AdminDBTopLevel(conFactory);
return adminDbTopLevel.getUserSimCounts(pastTime_days);
}

public MathVerifier getMathVerifier() throws DataAccessException, SQLException {
LocalAdminDbServer adminDbServer = new LocalAdminDbServer(conFactory, conFactory.getKeyFactory());
return new MathVerifier(conFactory, adminDbServer);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
package org.vcell.admin.cli.tools;

import cbit.vcell.modeldb.AdminDBTopLevel;
import cbit.vcell.resource.PropertyLoader;
import org.apache.logging.log4j.Level;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.apache.logging.log4j.core.LoggerContext;
import org.vcell.admin.cli.CLIDatabaseService;
import picocli.CommandLine.Command;
import picocli.CommandLine.Option;

import java.io.File;
import java.io.FileWriter;
import java.util.Arrays;
import java.util.Date;
import java.util.concurrent.Callable;

@Command(name = "users-query", description = "query vcell users")
public class UsersQueryCommand implements Callable<Integer> {

private final static Logger logger = LogManager.getLogger(UsersQueryCommand.class);

@Option(names = {"-o", "--outputFile"}, required = true)
private File outputFilePath;

@Option(names = {"-s", "--start"}, required = true, description = "start date for query (format: yyyy-MM-dd)")
Date startDate;

@Option(names = {"-n", "--notify"}, description = "filter users by notify=true")
private boolean notify;

@Option(names = {"-d", "--debug"}, required = false, defaultValue = "false", description = "full application debug mode")
private boolean bDebug = false;

public Integer call() {
Level logLevel = bDebug ? Level.DEBUG : logger.getLevel();

LoggerContext config = (LoggerContext) (LogManager.getContext(false));
config.getConfiguration().getLoggerConfig(LogManager.getLogger("org.vcell").getName()).setLevel(logLevel);
config.getConfiguration().getLoggerConfig(LogManager.getLogger("cbit").getName()).setLevel(logLevel);
config.updateLoggers();

try {
PropertyLoader.loadProperties(new String[]{ PropertyLoader.dbDriverName, PropertyLoader.dbConnectURL,
PropertyLoader.dbUserid, PropertyLoader.dbPasswordValue});

try (CLIDatabaseService cliDatabaseService = new CLIDatabaseService()) {
long pastTime_days = (new Date().getTime() - startDate.getTime()) / (1000 * 60 * 60 * 24);
System.out.println("pastTime_days: " + pastTime_days + " days since " + startDate);
AdminDBTopLevel.DbUserSimCount[] userSimCounts = cliDatabaseService.getUserSimCount((int) pastTime_days);
// filter out users by notify flag
if (notify) {
userSimCounts = Arrays.stream(userSimCounts)
.filter(userSimCount -> userSimCount.notify_value() == AdminDBTopLevel.NotifyValue.on)
.toArray(AdminDBTopLevel.DbUserSimCount[]::new);
}
// sort by userid
Arrays.sort(userSimCounts, (o1, o2) -> o1.userid().compareTo(o2.userid()));
try (FileWriter fileWriter = new FileWriter(outputFilePath)) {
// write out as a csv file
// header
fileWriter.write("userid,userkey,email,firstname,lastname,notify,simcount");
fileWriter.write("\n");
for (AdminDBTopLevel.DbUserSimCount userSimCount : userSimCounts) {
fileWriter.write(userSimCount.userid() + ",");
fileWriter.write(userSimCount.userkey().toString() + ",");
fileWriter.write(userSimCount.email() + ",");
fileWriter.write(userSimCount.firstname() + ",");
fileWriter.write(userSimCount.lastname() + ",");
fileWriter.write(userSimCount.notify_value() + ",");
fileWriter.write(userSimCount.simCount() + "");
fileWriter.write("\n");
}
}
} catch (RuntimeException e) {
e.printStackTrace(System.err);
}
return 0;
} catch (Exception e) {
e.printStackTrace();
throw new RuntimeException(e.getMessage());
}
}
}
55 changes: 48 additions & 7 deletions vcell-server/src/main/java/cbit/vcell/modeldb/AdminDBTopLevel.java
Original file line number Diff line number Diff line change
Expand Up @@ -264,6 +264,10 @@ private static int executeCountQuery(Statement stmt, String query) throws SQLExc
return val;
}

public enum NotifyValue {
on, off, bounce, unknown
}


public record DbUsageSummary(
DbUserSimCount[] simCounts_7Days,
Expand All @@ -281,7 +285,7 @@ public record DbUsageSummary(
int simCount,
int publicBiomodelSimCount,
int publicMathmodelSimCount) {}
public record DbUserSimCount(String username, int simCount) {}
public record DbUserSimCount(String userid, KeyValue userkey, String firstname, String lastname, String email, NotifyValue notify_value, int simCount) {}
public record DbUsersRegisteredStats(int last1Week, int last1Month, int last3Months, int last6Months, int last12Months) {}

public synchronized DbUsageSummary getUsageSummary(User.SpecialUser user) throws SQLException, DataAccessException{
Expand Down Expand Up @@ -375,18 +379,55 @@ public synchronized DbUsageSummary getUsageSummary(User.SpecialUser user) throws
}
}

private DbUserSimCount[] getUserSimCounts(Statement stmt, int pastTime) throws SQLException {
public DbUserSimCount[] getUserSimCounts(int pastTime_days) throws SQLException, DataAccessException{
Object lock = new Object();
Connection con = conFactory.getConnection(lock);
Statement stmt = null;
try {
stmt = con.createStatement();
return getUserSimCounts(stmt, pastTime_days);
} catch(Throwable e){
lg.error("failure in getSimulationJobStatusArray()", e);
handle_DataAccessException_SQLException(e);
return null; // never gets here;
} finally {
try {
if(stmt != null){
stmt.close();
}
} catch(Exception e){
lg.error(e.getMessage(), e);
}
conFactory.release(con, lock);
}
}

private DbUserSimCount[] getUserSimCounts(Statement stmt, int pastTime_days) throws SQLException {
ResultSet rset = stmt.executeQuery(
"SELECT userid, COUNT(vc_simulationjob.id) simcount FROM vc_userinfo, vc_simulation, vc_simulationjob"
"SELECT userid, vc_userinfo.id, email, firstname, lastname, notify, COUNT(vc_simulationjob.id) simcount FROM vc_userinfo, vc_simulation, vc_simulationjob"
+ " WHERE vc_userinfo.id = vc_simulation.ownerref AND "
+ "vc_simulationjob.simref = vc_simulation.id AND "
+ "vc_simulationjob.submitdate >= (CURRENT_DATE -" + pastTime + ")" + " GROUP BY userid ORDER BY simcount desc");
+ "vc_simulationjob.submitdate >= (CURRENT_DATE -" + pastTime_days + ")" + " GROUP BY userid, vc_userinfo.id, email, firstname, lastname, notify ORDER BY simcount desc");
ArrayList<DbUserSimCount> userSimCounts = new ArrayList<>();
HashSet<NotifyValue> notify_values = new HashSet<>();
while (rset.next()) {
String username = rset.getString(1);
int userSimCount = rset.getInt(2);
userSimCounts.add(new DbUserSimCount(username, userSimCount));
String userid = rset.getString(1);
KeyValue userkey = new KeyValue(rset.getBigDecimal(2));
String email = rset.getString(3);
String firstname = rset.getString(4);
String lastname = rset.getString(5);
String notify_str = rset.getString(6);
NotifyValue notify_value = null;
try {
notify_value = NotifyValue.valueOf(notify_str);
}catch (Exception e){
lg.error("failed to parse boolean value: " + notify_str, e);
}
notify_values.add(notify_value);
int userSimCount = rset.getInt(7);
userSimCounts.add(new DbUserSimCount(userid, userkey, firstname, lastname, email, notify_value, userSimCount));
}
System.out.println("notify string values is " + notify_values);
rset.close();
return userSimCounts.toArray(new DbUserSimCount[0]);
}
Expand Down

0 comments on commit 3e40e24

Please sign in to comment.