This is an automated email from the ASF dual-hosted git repository.
rickyma pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/incubator-uniffle.git
The following commit(s) were added to refs/heads/master by this push:
new bcd6b0788 [#1860] feat(CLI/Coordinator/Dashboard): Add Reg time to
AppInfo and Application (#1861)
bcd6b0788 is described below
commit bcd6b0788a57eb07d4b52796dcdc6e8826d2a14a
Author: maobaolong <[email protected]>
AuthorDate: Thu Jul 4 15:10:55 2024 +0800
[#1860] feat(CLI/Coordinator/Dashboard): Add Reg time to AppInfo and
Application (#1861)
### What changes were proposed in this pull request?
Add Reg time to AppInfo and Application
### Why are the changes needed?
Fix: #1860
### Does this PR introduce _any_ user-facing change?
`bin/uniffle client-cli -app -host localhost -port 19998` and dashboard
app page will display registrationTime of each application.
### How was this patch tested?
```Console
bin/uniffle client-cli -app -host localhost -port 19998
host:localhost,port:19998
+--------------------------------------------------------------------------------------------------------------+
| Uniffle Applications
|
+---------------------------------------+------+---------------------+---------------------+-------------------+
| ApplicationId | User | Registration Time |
Last HeartBeatTime | RemoteStoragePath |
+---------------------------------------+------+---------------------+---------------------+-------------------+
| app-20240703231912-0003_1720019950472 | user | 2024-07-03 23:19:40 |
2024-07-03 23:21:05 | null |
| app-20240703232127-0004_1720020086199 | user | 2024-07-03 23:21:51 |
2024-07-03 23:22:16 | null |
+---------------------------------------+------+---------------------+---------------------+-------------------+
```
<img width="1508" alt="image"
src="https://github.com/apache/incubator-uniffle/assets/17329931/96f9703d-6c99-4600-adb5-2ddd8ae48c4d">
---
.../java/org/apache/uniffle/cli/UniffleCLI.java | 4 +-
.../org/apache/uniffle/common/Application.java | 21 ++++++++++
.../{web/vo/AppInfoVO.java => AppInfo.java} | 46 ++++++++++++----------
.../uniffle/coordinator/ApplicationManager.java | 43 ++++++++++++--------
.../apache/uniffle/coordinator/QuotaManager.java | 29 ++++++++++----
.../web/resource/ApplicationResource.java | 19 +++++----
.../uniffle/coordinator/web/vo/AppInfoVO.java | 17 ++++++--
.../uniffle/coordinator/QuotaManagerTest.java | 37 +++++++++++------
.../src/main/webapp/src/pages/ApplicationPage.vue | 3 +-
9 files changed, 151 insertions(+), 68 deletions(-)
diff --git a/cli/src/main/java/org/apache/uniffle/cli/UniffleCLI.java
b/cli/src/main/java/org/apache/uniffle/cli/UniffleCLI.java
index 7c7c66fb4..f1ce006c3 100644
--- a/cli/src/main/java/org/apache/uniffle/cli/UniffleCLI.java
+++ b/cli/src/main/java/org/apache/uniffle/cli/UniffleCLI.java
@@ -59,7 +59,8 @@ public class UniffleCLI extends AbstractCustomCommandLine {
private final Option help;
private static final List<String> APPLICATIONS_HEADER =
- Arrays.asList("ApplicationId", "User", "Last HeartBeatTime",
"RemoteStoragePath");
+ Arrays.asList(
+ "ApplicationId", "User", "Registration Time", "Last HeartBeatTime",
"RemoteStoragePath");
public UniffleCLI(String shortPrefix, String longPrefix) {
allOptions = new Options();
@@ -222,6 +223,7 @@ public class UniffleCLI extends AbstractCustomCommandLine {
formattingCLIUtils.addLine(
app.getApplicationId(),
app.getUser(),
+ app.getRegistrationTime(),
app.getLastHeartBeatTime(),
app.getRemoteStoragePath()));
}
diff --git a/common/src/main/java/org/apache/uniffle/common/Application.java
b/common/src/main/java/org/apache/uniffle/common/Application.java
index 688144223..27d683e7e 100644
--- a/common/src/main/java/org/apache/uniffle/common/Application.java
+++ b/common/src/main/java/org/apache/uniffle/common/Application.java
@@ -28,6 +28,7 @@ public class Application implements Comparable<Application> {
private String user;
private String lastHeartBeatTime;
private String remoteStoragePath;
+ private String registrationTime;
public Application() {}
@@ -36,12 +37,14 @@ public class Application implements Comparable<Application>
{
this.user = builder.user;
this.lastHeartBeatTime = builder.lastHeartBeatTime;
this.remoteStoragePath = builder.remoteStoragePath;
+ this.registrationTime = builder.registrationTime;
}
public static class Builder {
private String applicationId;
private String user;
private String lastHeartBeatTime;
+ private String registrationTime;
private String remoteStoragePath;
public Builder() {}
@@ -61,6 +64,11 @@ public class Application implements Comparable<Application> {
return this;
}
+ public Builder registrationTime(long registrationTime) {
+ this.registrationTime = DateFormatUtils.format(registrationTime,
DATE_PATTERN);
+ return this;
+ }
+
public Builder remoteStoragePath(RemoteStorageInfo remoteStorageInfo) {
if (remoteStorageInfo != null) {
this.remoteStoragePath = remoteStorageInfo.getPath();
@@ -85,6 +93,10 @@ public class Application implements Comparable<Application> {
return lastHeartBeatTime;
}
+ public String getRegistrationTime() {
+ return registrationTime;
+ }
+
public String getRemoteStoragePath() {
return remoteStoragePath;
}
@@ -101,6 +113,10 @@ public class Application implements
Comparable<Application> {
this.lastHeartBeatTime = lastHeartBeatTime;
}
+ public void setRegistrationTime(String registrationTime) {
+ this.registrationTime = registrationTime;
+ }
+
public void setRemoteStoragePath(String remoteStoragePath) {
this.remoteStoragePath = remoteStoragePath;
}
@@ -115,6 +131,7 @@ public class Application implements Comparable<Application>
{
.append(this.getApplicationId(), otherImpl.getApplicationId())
.append(this.getUser(), otherImpl.getUser())
.append(this.getLastHeartBeatTime(), otherImpl.getLastHeartBeatTime())
+ .append(this.getRegistrationTime(), otherImpl.getRegistrationTime())
.append(this.getRemoteStoragePath(), otherImpl.getRemoteStoragePath())
.isEquals();
}
@@ -125,6 +142,7 @@ public class Application implements Comparable<Application>
{
.append(this.getApplicationId())
.append(this.getUser())
.append(this.getLastHeartBeatTime())
+ .append(this.getRegistrationTime())
.append(this.getRemoteStoragePath())
.toHashCode();
}
@@ -146,6 +164,9 @@ public class Application implements Comparable<Application>
{
+ ", lastHeartBeatTime='"
+ lastHeartBeatTime
+ '\''
+ + ", registrationTime='"
+ + registrationTime
+ + '\''
+ ", remoteStoragePath='"
+ remoteStoragePath
+ '\''
diff --git
a/coordinator/src/main/java/org/apache/uniffle/coordinator/web/vo/AppInfoVO.java
b/coordinator/src/main/java/org/apache/uniffle/coordinator/AppInfo.java
similarity index 60%
copy from
coordinator/src/main/java/org/apache/uniffle/coordinator/web/vo/AppInfoVO.java
copy to coordinator/src/main/java/org/apache/uniffle/coordinator/AppInfo.java
index 87ee82683..d9e9f9953 100644
---
a/coordinator/src/main/java/org/apache/uniffle/coordinator/web/vo/AppInfoVO.java
+++ b/coordinator/src/main/java/org/apache/uniffle/coordinator/AppInfo.java
@@ -15,27 +15,19 @@
* limitations under the License.
*/
-package org.apache.uniffle.coordinator.web.vo;
+package org.apache.uniffle.coordinator;
import java.util.Objects;
-public class AppInfoVO implements Comparable<AppInfoVO> {
- private String userName;
+public class AppInfo implements Comparable<AppInfo> {
private String appId;
private long updateTime;
+ private long registrationTime;
- public AppInfoVO(String userName, String appId, long updateTime) {
- this.userName = userName;
+ public AppInfo(String appId, long updateTime, long registrationTime) {
this.appId = appId;
this.updateTime = updateTime;
- }
-
- public String getUserName() {
- return userName;
- }
-
- public void setUserName(String userName) {
- this.userName = userName;
+ this.registrationTime = registrationTime;
}
public String getAppId() {
@@ -54,9 +46,17 @@ public class AppInfoVO implements Comparable<AppInfoVO> {
this.updateTime = updateTime;
}
+ public long getRegistrationTime() {
+ return registrationTime;
+ }
+
+ public void setRegistrationTime(long registrationTime) {
+ this.registrationTime = registrationTime;
+ }
+
@Override
- public int compareTo(AppInfoVO appInfoVO) {
- return Long.compare(updateTime, appInfoVO.getUpdateTime());
+ public int compareTo(AppInfo appInfo) {
+ return Long.compare(registrationTime, appInfo.getRegistrationTime());
}
@Override
@@ -64,17 +64,21 @@ public class AppInfoVO implements Comparable<AppInfoVO> {
if (this == o) {
return true;
}
- if (!(o instanceof AppInfoVO)) {
+ if (!(o instanceof AppInfo)) {
return false;
}
- AppInfoVO appInfoVO = (AppInfoVO) o;
- return updateTime == appInfoVO.updateTime
- && userName.equals(appInfoVO.userName)
- && appId.equals(appInfoVO.appId);
+ AppInfo appInfo = (AppInfo) o;
+ return updateTime == appInfo.updateTime
+ && registrationTime == appInfo.registrationTime
+ && appId.equals(appInfo.appId);
}
@Override
public int hashCode() {
- return Objects.hash(userName, appId, updateTime);
+ return Objects.hash(appId, updateTime, registrationTime);
+ }
+
+ public static AppInfo createAppInfo(String appId, long updateTime) {
+ return new AppInfo(appId, updateTime, updateTime);
}
}
diff --git
a/coordinator/src/main/java/org/apache/uniffle/coordinator/ApplicationManager.java
b/coordinator/src/main/java/org/apache/uniffle/coordinator/ApplicationManager.java
index 70e90ffa6..716c22692 100644
---
a/coordinator/src/main/java/org/apache/uniffle/coordinator/ApplicationManager.java
+++
b/coordinator/src/main/java/org/apache/uniffle/coordinator/ApplicationManager.java
@@ -72,7 +72,7 @@ public class ApplicationManager implements Closeable {
private final Map<String, RemoteStorageInfo> availableRemoteStorageInfo;
private final ScheduledExecutorService detectStorageScheduler;
private final ScheduledExecutorService checkAppScheduler;
- private Map<String, Map<String, Long>> currentUserAndApp =
JavaUtils.newConcurrentMap();
+ private Map<String, Map<String, AppInfo>> currentUserAndApp =
JavaUtils.newConcurrentMap();
private Map<String, String> appIdToUser = JavaUtils.newConcurrentMap();
private QuotaManager quotaManager;
// it's only for test case to check if status check has problem
@@ -130,17 +130,18 @@ public class ApplicationManager implements Closeable {
// implementation class
// in such case by default, there is no currentUserAndApp, so a unified
user implementation
// named "user" is used.
- Map<String, Long> appAndTime =
+ Map<String, AppInfo> appAndTime =
currentUserAndApp.computeIfAbsent(user, x ->
JavaUtils.newConcurrentMap());
appIdToUser.put(appId, user);
if (!appAndTime.containsKey(appId)) {
CoordinatorMetrics.counterTotalAppNum.inc();
LOG.info("New application is registered: {}", appId);
}
+ AppInfo appInfo = AppInfo.createAppInfo(appId, System.currentTimeMillis());
if (quotaManager != null) {
quotaManager.registerApplicationInfo(appId, appAndTime);
} else {
- appAndTime.put(appId, System.currentTimeMillis());
+ appAndTime.put(appId, appInfo);
}
}
@@ -150,8 +151,15 @@ public class ApplicationManager implements Closeable {
if (user == null) {
registerApplicationInfo(appId, "");
} else {
- Map<String, Long> appAndTime = currentUserAndApp.get(user);
- appAndTime.put(appId, System.currentTimeMillis());
+ Map<String, AppInfo> appAndTime = currentUserAndApp.get(user);
+ AppInfo appInfo = appAndTime.get(appId);
+ long currentTimeMs = System.currentTimeMillis();
+ if (appInfo != null) {
+ appInfo.setUpdateTime(currentTimeMs);
+ } else {
+ appInfo = new AppInfo(appId, currentTimeMs, currentTimeMs);
+ appAndTime.put(appId, appInfo);
+ }
}
}
@@ -317,8 +325,8 @@ public class ApplicationManager implements Closeable {
}
protected void statusCheck() {
- List<Map<String, Long>> appAndNums =
Lists.newArrayList(currentUserAndApp.values());
- Map<String, Long> appIds = Maps.newHashMap();
+ List<Map<String, AppInfo>> appAndNums =
Lists.newArrayList(currentUserAndApp.values());
+ Map<String, AppInfo> appIds = Maps.newHashMap();
// The reason for setting an expired uuid here is that there is a scenario
where accessCluster
// succeeds,
// but the registration of shuffle fails, resulting in no normal
heartbeat, and no normal update
@@ -326,12 +334,12 @@ public class ApplicationManager implements Closeable {
// Therefore, an expiration time is set to automatically remove expired
uuids
Set<String> expiredAppIds = Sets.newHashSet();
try {
- for (Map<String, Long> appAndTimes : appAndNums) {
- for (Map.Entry<String, Long> appAndTime : appAndTimes.entrySet()) {
+ for (Map<String, AppInfo> appAndTimes : appAndNums) {
+ for (Map.Entry<String, AppInfo> appAndTime : appAndTimes.entrySet()) {
String appId = appAndTime.getKey();
- long lastReport = appAndTime.getValue();
+ AppInfo lastReport = appAndTime.getValue();
appIds.put(appId, lastReport);
- if (System.currentTimeMillis() - lastReport > expired) {
+ if (System.currentTimeMillis() - lastReport.getUpdateTime() >
expired) {
expiredAppIds.add(appId);
appAndTimes.remove(appId);
appIdToUser.remove(appId);
@@ -416,11 +424,11 @@ public class ApplicationManager implements Closeable {
String pHeartBeatEndTime,
String appIdRegex) {
List<Application> applications = new ArrayList<>();
- for (Map.Entry<String, Map<String, Long>> entry :
currentUserAndApp.entrySet()) {
+ for (Map.Entry<String, Map<String, AppInfo>> entry :
currentUserAndApp.entrySet()) {
String user = entry.getKey();
- Map<String, Long> apps = entry.getValue();
+ Map<String, AppInfo> apps = entry.getValue();
apps.forEach(
- (appId, heartBeatTime) -> {
+ (appId, appInfo) -> {
// Filter condition 1: Check whether applicationId is included in
the filter list.
boolean match = appIds.size() == 0 || appIds.contains(appId);
@@ -435,7 +443,7 @@ public class ApplicationManager implements Closeable {
|| StringUtils.isNotBlank(pHeartBeatEndTime)) {
match =
matchHeartBeatStartTimeAndEndTime(
- pHeartBeatStartTime, pHeartBeatEndTime, heartBeatTime);
+ pHeartBeatStartTime, pHeartBeatEndTime,
appInfo.getUpdateTime());
}
// If it meets expectations, add to the list to be returned.
@@ -446,7 +454,8 @@ public class ApplicationManager implements Closeable {
new Application.Builder()
.applicationId(appId)
.user(user)
- .lastHeartBeatTime(heartBeatTime)
+ .lastHeartBeatTime(appInfo.getUpdateTime())
+ .registrationTime(appInfo.getRegistrationTime())
.remoteStoragePath(remoteStorageInfo)
.build();
applications.add(application);
@@ -527,7 +536,7 @@ public class ApplicationManager implements Closeable {
return REMOTE_PATH_SCHEMA;
}
- public Map<String, Map<String, Long>> getCurrentUserAndApp() {
+ public Map<String, Map<String, AppInfo>> getCurrentUserAndApp() {
return currentUserAndApp;
}
diff --git
a/coordinator/src/main/java/org/apache/uniffle/coordinator/QuotaManager.java
b/coordinator/src/main/java/org/apache/uniffle/coordinator/QuotaManager.java
index d661f90df..72c462933 100644
--- a/coordinator/src/main/java/org/apache/uniffle/coordinator/QuotaManager.java
+++ b/coordinator/src/main/java/org/apache/uniffle/coordinator/QuotaManager.java
@@ -44,7 +44,7 @@ import
org.apache.uniffle.coordinator.metric.CoordinatorMetrics;
/** QuotaManager is a manager for resource restriction. */
public class QuotaManager {
private static final Logger LOG =
LoggerFactory.getLogger(QuotaManager.class);
- private final Map<String, Map<String, Long>> currentUserAndApp =
JavaUtils.newConcurrentMap();
+ private final Map<String, Map<String, AppInfo>> currentUserAndApp =
JavaUtils.newConcurrentMap();
private final Map<String, String> appIdToUser = JavaUtils.newConcurrentMap();
private final String quotaFilePath;
private final Integer quotaAppNum;
@@ -116,7 +116,7 @@ public class QuotaManager {
}
public boolean checkQuota(String user, String uuid) {
- Map<String, Long> appAndTimes =
+ Map<String, AppInfo> appAndTimes =
currentUserAndApp.computeIfAbsent(user, x ->
JavaUtils.newConcurrentMap());
Integer userAppQuotaNum = defaultUserApps.computeIfAbsent(user, x ->
quotaAppNum);
synchronized (this) {
@@ -124,26 +124,41 @@ public class QuotaManager {
if (userAppQuotaNum >= 0 && currentAppNum >= userAppQuotaNum) {
return true;
} else {
- appAndTimes.put(uuid, System.currentTimeMillis());
+ // thread safe is guaranteed by synchronized
+ AppInfo appInfo = appAndTimes.get(uuid);
+ long currentTimeMillis = System.currentTimeMillis();
+ if (appInfo == null) {
+ appInfo = new AppInfo(uuid, currentTimeMillis, currentTimeMillis);
+ appAndTimes.put(uuid, appInfo);
+ } else {
+ appInfo.setUpdateTime(currentTimeMillis);
+ }
CoordinatorMetrics.gaugeRunningAppNumToUser.labels(user).inc();
return false;
}
}
}
- public void registerApplicationInfo(String appId, Map<String, Long>
appAndTime) {
+ public void registerApplicationInfo(String appId, Map<String, AppInfo>
appAndTime) {
long currentTimeMillis = System.currentTimeMillis();
String[] appIdAndUuid = appId.split("_");
String uuidFromApp = appIdAndUuid[appIdAndUuid.length - 1];
// if appId created successfully, we need to remove the uuid
synchronized (this) {
appAndTime.remove(uuidFromApp);
- appAndTime.put(appId, currentTimeMillis);
+ // thread safe is guaranteed by synchronized
+ AppInfo appInfo = appAndTime.get(appId);
+ if (appInfo == null) {
+ appInfo = new AppInfo(appId, currentTimeMillis, currentTimeMillis);
+ appAndTime.put(appId, appInfo);
+ } else {
+ appInfo.setUpdateTime(currentTimeMillis);
+ }
}
}
protected void updateQuotaMetrics() {
- for (Map.Entry<String, Map<String, Long>> userAndApp :
currentUserAndApp.entrySet()) {
+ for (Map.Entry<String, Map<String, AppInfo>> userAndApp :
currentUserAndApp.entrySet()) {
String user = userAndApp.getKey();
try {
CoordinatorMetrics.gaugeRunningAppNumToUser.labels(user).set(userAndApp.getValue().size());
@@ -158,7 +173,7 @@ public class QuotaManager {
return defaultUserApps;
}
- public Map<String, Map<String, Long>> getCurrentUserAndApp() {
+ public Map<String, Map<String, AppInfo>> getCurrentUserAndApp() {
return currentUserAndApp;
}
diff --git
a/coordinator/src/main/java/org/apache/uniffle/coordinator/web/resource/ApplicationResource.java
b/coordinator/src/main/java/org/apache/uniffle/coordinator/web/resource/ApplicationResource.java
index 7106d66d1..12558639a 100644
---
a/coordinator/src/main/java/org/apache/uniffle/coordinator/web/resource/ApplicationResource.java
+++
b/coordinator/src/main/java/org/apache/uniffle/coordinator/web/resource/ApplicationResource.java
@@ -32,6 +32,7 @@ import org.apache.hbase.thirdparty.javax.ws.rs.core.MediaType;
import org.apache.uniffle.common.web.resource.BaseResource;
import org.apache.uniffle.common.web.resource.Response;
+import org.apache.uniffle.coordinator.AppInfo;
import org.apache.uniffle.coordinator.ApplicationManager;
import org.apache.uniffle.coordinator.web.vo.AppInfoVO;
import org.apache.uniffle.coordinator.web.vo.UserAppNumVO;
@@ -57,10 +58,11 @@ public class ApplicationResource extends BaseResource {
public Response<List<UserAppNumVO>> getUserApps() {
return execute(
() -> {
- Map<String, Map<String, Long>> currentUserAndApp =
+ Map<String, Map<String, AppInfo>> currentUserAndApp =
getApplicationManager().getCurrentUserAndApp();
List<UserAppNumVO> usercnt = new ArrayList<>();
- for (Map.Entry<String, Map<String, Long>> stringMapEntry :
currentUserAndApp.entrySet()) {
+ for (Map.Entry<String, Map<String, AppInfo>> stringMapEntry :
+ currentUserAndApp.entrySet()) {
String userName = stringMapEntry.getKey();
usercnt.add(new UserAppNumVO(userName,
stringMapEntry.getValue().size()));
}
@@ -76,16 +78,19 @@ public class ApplicationResource extends BaseResource {
return execute(
() -> {
List<AppInfoVO> userToAppList = new ArrayList<>();
- Map<String, Map<String, Long>> currentUserAndApp =
+ Map<String, Map<String, AppInfo>> currentUserAndApp =
getApplicationManager().getCurrentUserAndApp();
- for (Map.Entry<String, Map<String, Long>> userAppIdTimestampMap :
+ for (Map.Entry<String, Map<String, AppInfo>> userAppIdTimestampMap :
currentUserAndApp.entrySet()) {
- String userName = userAppIdTimestampMap.getKey();
- for (Map.Entry<String, Long> appIdTimestampMap :
+ for (Map.Entry<String, AppInfo> appIdTimestampMap :
userAppIdTimestampMap.getValue().entrySet()) {
+ AppInfo appInfo = appIdTimestampMap.getValue();
userToAppList.add(
new AppInfoVO(
- userName, appIdTimestampMap.getKey(),
appIdTimestampMap.getValue()));
+ userAppIdTimestampMap.getKey(),
+ appInfo.getAppId(),
+ appInfo.getUpdateTime(),
+ appInfo.getRegistrationTime()));
}
}
// Display is inverted by the submission time of the application.
diff --git
a/coordinator/src/main/java/org/apache/uniffle/coordinator/web/vo/AppInfoVO.java
b/coordinator/src/main/java/org/apache/uniffle/coordinator/web/vo/AppInfoVO.java
index 87ee82683..3d80f0e01 100644
---
a/coordinator/src/main/java/org/apache/uniffle/coordinator/web/vo/AppInfoVO.java
+++
b/coordinator/src/main/java/org/apache/uniffle/coordinator/web/vo/AppInfoVO.java
@@ -23,11 +23,13 @@ public class AppInfoVO implements Comparable<AppInfoVO> {
private String userName;
private String appId;
private long updateTime;
+ private long registrationTime;
- public AppInfoVO(String userName, String appId, long updateTime) {
+ public AppInfoVO(String userName, String appId, long updateTime, long
registrationTime) {
this.userName = userName;
this.appId = appId;
this.updateTime = updateTime;
+ this.registrationTime = registrationTime;
}
public String getUserName() {
@@ -54,9 +56,17 @@ public class AppInfoVO implements Comparable<AppInfoVO> {
this.updateTime = updateTime;
}
+ public long getRegistrationTime() {
+ return registrationTime;
+ }
+
+ public void setRegistrationTime(long registrationTime) {
+ this.registrationTime = registrationTime;
+ }
+
@Override
public int compareTo(AppInfoVO appInfoVO) {
- return Long.compare(updateTime, appInfoVO.getUpdateTime());
+ return Long.compare(registrationTime, appInfoVO.getRegistrationTime());
}
@Override
@@ -69,12 +79,13 @@ public class AppInfoVO implements Comparable<AppInfoVO> {
}
AppInfoVO appInfoVO = (AppInfoVO) o;
return updateTime == appInfoVO.updateTime
+ && registrationTime == appInfoVO.registrationTime
&& userName.equals(appInfoVO.userName)
&& appId.equals(appInfoVO.appId);
}
@Override
public int hashCode() {
- return Objects.hash(userName, appId, updateTime);
+ return Objects.hash(userName, appId, updateTime, registrationTime);
}
}
diff --git
a/coordinator/src/test/java/org/apache/uniffle/coordinator/QuotaManagerTest.java
b/coordinator/src/test/java/org/apache/uniffle/coordinator/QuotaManagerTest.java
index 41be903c2..54c0f9b47 100644
---
a/coordinator/src/test/java/org/apache/uniffle/coordinator/QuotaManagerTest.java
+++
b/coordinator/src/test/java/org/apache/uniffle/coordinator/QuotaManagerTest.java
@@ -97,14 +97,20 @@ public class QuotaManagerTest {
conf.setInteger(CoordinatorConf.COORDINATOR_QUOTA_DEFAULT_APP_NUM, 5);
try (ApplicationManager applicationManager = new ApplicationManager(conf))
{
final AtomicInteger uuid = new AtomicInteger();
- Map<String, Long> uuidAndTime = JavaUtils.newConcurrentMap();
- uuidAndTime.put(String.valueOf(uuid.incrementAndGet()),
System.currentTimeMillis());
- uuidAndTime.put(String.valueOf(uuid.incrementAndGet()),
System.currentTimeMillis());
- uuidAndTime.put(String.valueOf(uuid.incrementAndGet()),
System.currentTimeMillis());
- uuidAndTime.put(String.valueOf(uuid.incrementAndGet()),
System.currentTimeMillis());
+ Map<String, AppInfo> uuidAndTime = JavaUtils.newConcurrentMap();
+ String appId = String.valueOf(uuid.incrementAndGet());
+ uuidAndTime.put(appId, AppInfo.createAppInfo(appId,
System.currentTimeMillis()));
+ appId = String.valueOf(uuid.incrementAndGet());
+ uuidAndTime.put(appId, AppInfo.createAppInfo(appId,
System.currentTimeMillis()));
+ appId = String.valueOf(uuid.incrementAndGet());
+ uuidAndTime.put(appId, AppInfo.createAppInfo(appId,
System.currentTimeMillis()));
+ appId = String.valueOf(uuid.incrementAndGet());
+ uuidAndTime.put(appId, AppInfo.createAppInfo(appId,
System.currentTimeMillis()));
final int i1 = uuid.incrementAndGet();
- uuidAndTime.put(String.valueOf(i1), System.currentTimeMillis());
- Map<String, Long> appAndTime =
+ uuidAndTime.put(
+ String.valueOf(i1),
+ AppInfo.createAppInfo(String.valueOf(i1),
System.currentTimeMillis()));
+ Map<String, AppInfo> appAndTime =
applicationManager
.getQuotaManager()
.getCurrentUserAndApp()
@@ -184,7 +190,7 @@ public class QuotaManagerTest {
.until(() -> applicationManager.getDefaultUserApps().size() > 2);
QuotaManager quotaManager = applicationManager.getQuotaManager();
- Map<String, Map<String, Long>> currentUserAndApp =
quotaManager.getCurrentUserAndApp();
+ Map<String, Map<String, AppInfo>> currentUserAndApp =
quotaManager.getCurrentUserAndApp();
currentUserAndApp.computeIfAbsent("user1", x -> mockUUidAppAndTime(30));
currentUserAndApp.computeIfAbsent("user2", x -> mockUUidAppAndTime(20));
@@ -211,11 +217,20 @@ public class QuotaManagerTest {
return String.valueOf(uuid.incrementAndGet());
}
- private Map<String, Long> mockUUidAppAndTime(int mockAppNum) {
- Map<String, Long> uuidAndTime = JavaUtils.newConcurrentMap();
+ private Map<String, AppInfo> mockUUidAppAndTime(int mockAppNum) {
+ Map<String, AppInfo> uuidAndTime = JavaUtils.newConcurrentMap();
for (int i = 0; i < mockAppNum; i++) {
- uuidAndTime.put(mockUUidAppId(), System.currentTimeMillis());
+ String appId = mockUUidAppId();
+ long currentTimeMs = System.currentTimeMillis();
+ AppInfo appInfo = uuidAndTime.get(appId);
+ if (appInfo != null) {
+ appInfo.setUpdateTime(currentTimeMs);
+ } else {
+ appInfo = new AppInfo(appId, currentTimeMs, currentTimeMs);
+ uuidAndTime.put(appId, appInfo);
+ }
}
+
return uuidAndTime;
}
}
diff --git a/dashboard/src/main/webapp/src/pages/ApplicationPage.vue
b/dashboard/src/main/webapp/src/pages/ApplicationPage.vue
index 33d1e546c..e3ef4cab9 100644
--- a/dashboard/src/main/webapp/src/pages/ApplicationPage.vue
+++ b/dashboard/src/main/webapp/src/pages/ApplicationPage.vue
@@ -43,6 +43,7 @@
<el-table :data="pageData.appInfoData" height="250" style="width: 100%">
<el-table-column prop="appId" label="AppId" min-width="180" />
<el-table-column prop="userName" label="UserName" min-width="180" />
+ <el-table-column prop="registrationTime" label="Registration Time"
min-width="180" :formatter="dateFormatter" />
<el-table-column prop="updateTime" label="Update Time" min-width="180"
:formatter="dateFormatter" />
</el-table>
</div>
@@ -60,7 +61,7 @@ export default {
const pageData = reactive({
apptotal: {},
userAppCount: [{}],
- appInfoData: [{ appId: '', userName: '', updateTime: '' }]
+ appInfoData: [{ appId: '', userName: '', registrationTime: '',
updateTime: '' }]
})
const currentServerStore = useCurrentServerStore()