[ARVADOS-WORKBENCH2] updated: 1.4.1-205-gfd5e5f64

Git user git at public.arvados.org
Wed Jan 8 21:40:02 UTC 2020


Summary of changes:
 src/store/data-explorer/data-explorer-action.ts    | 10 ++++++
 .../data-explorer-middleware-service.ts            |  2 +-
 .../data-explorer/data-explorer-middleware.test.ts |  5 +--
 .../data-explorer/data-explorer-middleware.ts      | 38 ++++++++++++++++++++--
 src/store/data-explorer/data-explorer-reducer.ts   |  9 +++--
 src/store/processes/process.ts                     | 18 +++++++---
 src/store/processes/processes-actions.ts           |  5 ---
 src/websocket/websocket.ts                         | 18 ++++++----
 8 files changed, 82 insertions(+), 23 deletions(-)

       via  fd5e5f64dd771aef39c6fe48f6e28e4b1470024f (commit)
       via  e9a475f58a3f8f8637c81e4d359f37ce902a341b (commit)
       via  279d5bffb26c8fb7d3ac846af1b7c901c12389a0 (commit)
      from  16860c6f2fedc5c150cab796e93aa21067f28e97 (commit)

Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.


commit fd5e5f64dd771aef39c6fe48f6e28e4b1470024f
Author: Peter Amstutz <peter.amstutz at curii.com>
Date:   Wed Jan 8 16:39:16 2020 -0500

    15672: Fix NaN runtime
    
    Arvados-DCO-1.1-Signed-off-by: Peter Amstutz <peter.amstutz at curii.com>

diff --git a/src/store/processes/process.ts b/src/store/processes/process.ts
index ab8093b8..400d77cf 100644
--- a/src/store/processes/process.ts
+++ b/src/store/processes/process.ts
@@ -56,10 +56,20 @@ export const getSubprocesses = (uuid: string) => (resources: ResourcesState) =>
     return [];
 };
 
-export const getProcessRuntime = ({ container }: Process) =>
-    container
-        ? getTimeDiff(container.finishedAt || '', container.startedAt || '')
-        : 0;
+export const getProcessRuntime = ({ container }: Process) => {
+    if (container) {
+        if (container.startedAt === null) {
+            return 0;
+        }
+        if (container.finishedAt === null) {
+            // Count it from now
+            return new Date().getTime() - new Date(container.startedAt).getTime();
+        }
+        return getTimeDiff(container.finishedAt, container.startedAt);
+    } else {
+        return 0;
+    }
+};
 
 export const getProcessStatusColor = (status: string, { customs, palette }: ArvadosTheme) => {
     switch (status) {

commit e9a475f58a3f8f8637c81e4d359f37ce902a341b
Author: Peter Amstutz <peter.amstutz at curii.com>
Date:   Wed Jan 8 15:57:57 2020 -0500

    15672: Auto-update project panel on container activity
    
    Arvados-DCO-1.1-Signed-off-by: Peter Amstutz <peter.amstutz at curii.com>

diff --git a/src/store/processes/processes-actions.ts b/src/store/processes/processes-actions.ts
index bb60378c..ab51f9ca 100644
--- a/src/store/processes/processes-actions.ts
+++ b/src/store/processes/processes-actions.ts
@@ -21,9 +21,6 @@ import { getWorkflow, getWorkflowInputs } from "~/models/workflow";
 
 export const loadProcess = (containerRequestUuid: string) =>
     async (dispatch: Dispatch, getState: () => RootState, services: ServiceRepository): Promise<Process> => {
-        const response = await services.workflowService.list();
-        dispatch(runProcessPanelActions.SET_WORKFLOWS(response.items));
-
         const containerRequest = await services.containerRequestService.get(containerRequestUuid);
         dispatch<any>(updateResources([containerRequest]));
 
diff --git a/src/websocket/websocket.ts b/src/websocket/websocket.ts
index 1a5964b5..e367dba3 100644
--- a/src/websocket/websocket.ts
+++ b/src/websocket/websocket.ts
@@ -8,12 +8,13 @@ import { Config } from '~/common/config';
 import { WebSocketService } from './websocket-service';
 import { ResourceEventMessage } from './resource-event-message';
 import { ResourceKind } from '~/models/resource';
-// import { loadProcess } from '~/store/processes/processes-actions';
+import { loadProcess } from '~/store/processes/processes-actions';
 // import { loadContainers } from '~/store/processes/processes-actions';
 import { LogEventType } from '~/models/log';
 import { addProcessLogsPanelItem } from '../store/process-logs-panel/process-logs-panel-actions';
 // import { FilterBuilder } from "~/services/api/filter-builder";
 import { subprocessPanelActions } from "~/store/subprocess-panel/subprocess-panel-actions";
+import { projectPanelActions } from "~/store/project-panel/project-panel-action";
 
 export const initWebSocket = (config: Config, authService: AuthService, store: RootStore) => {
     if (config.websocketUrl) {
@@ -29,12 +30,13 @@ const messageListener = (store: RootStore) => (message: ResourceEventMessage) =>
     if (message.eventType === LogEventType.CREATE || message.eventType === LogEventType.UPDATE) {
         switch (message.objectKind) {
             case ResourceKind.CONTAINER_REQUEST:
-            // return store.dispatch(loadProcess(message.objectUuid));
+                if (store.getState().processPanel.containerRequestUuid === message.objectUuid) {
+                    store.dispatch(loadProcess(message.objectUuid));
+                }
             case ResourceKind.CONTAINER:
-                // return store.dispatch(loadContainers(
-                //     new FilterBuilder().addIn('uuid', [message.objectUuid]).getFilters()
-                // ));
                 store.dispatch(subprocessPanelActions.REQUEST_ITEMS());
+                store.dispatch(projectPanelActions.REQUEST_ITEMS());
+                return;
             default:
                 return;
         }

commit 279d5bffb26c8fb7d3ac846af1b7c901c12389a0
Author: Peter Amstutz <peter.amstutz at curii.com>
Date:   Wed Jan 8 15:11:57 2020 -0500

    15672: Rate limiting for data explorer refresh
    
    Arvados-DCO-1.1-Signed-off-by: Peter Amstutz <peter.amstutz at curii.com>

diff --git a/src/store/data-explorer/data-explorer-action.ts b/src/store/data-explorer/data-explorer-action.ts
index 546ec8f3..80b743a2 100644
--- a/src/store/data-explorer/data-explorer-action.ts
+++ b/src/store/data-explorer/data-explorer-action.ts
@@ -6,10 +6,17 @@ import { unionize, ofType, UnionOf } from "~/common/unionize";
 import { DataColumns, DataTableFetchMode } from "~/components/data-table/data-table";
 import { DataTableFilters } from '~/components/data-table-filters/data-table-filters-tree';
 
+export enum DataTableRequestState {
+    IDLE,
+    PENDING,
+    NEED_REFRESH
+}
+
 export const dataExplorerActions = unionize({
     CLEAR: ofType<{ id: string }>(),
     RESET_PAGINATION: ofType<{ id: string }>(),
     REQUEST_ITEMS: ofType<{ id: string, criteriaChanged?: boolean }>(),
+    REQUEST_STATE: ofType<{ id: string, criteriaChanged?: boolean }>(),
     SET_FETCH_MODE: ofType<({ id: string, fetchMode: DataTableFetchMode })>(),
     SET_COLUMNS: ofType<{ id: string, columns: DataColumns<any> }>(),
     SET_FILTERS: ofType<{ id: string, columnName: string, filters: DataTableFilters }>(),
@@ -20,6 +27,7 @@ export const dataExplorerActions = unionize({
     TOGGLE_COLUMN: ofType<{ id: string, columnName: string }>(),
     TOGGLE_SORT: ofType<{ id: string, columnName: string }>(),
     SET_EXPLORER_SEARCH_VALUE: ofType<{ id: string, searchValue: string }>(),
+    SET_REQUEST_STATE: ofType<{ id: string, requestState: DataTableRequestState }>(),
 });
 
 export type DataExplorerAction = UnionOf<typeof dataExplorerActions>;
@@ -51,4 +59,6 @@ export const bindDataExplorerActions = (id: string) => ({
         dataExplorerActions.TOGGLE_SORT({ ...payload, id }),
     SET_EXPLORER_SEARCH_VALUE: (payload: { searchValue: string }) =>
         dataExplorerActions.SET_EXPLORER_SEARCH_VALUE({ ...payload, id }),
+    SET_REQUEST_STATE: (payload: { requestState: DataTableRequestState }) =>
+        dataExplorerActions.SET_REQUEST_STATE({ ...payload, id })
 });
diff --git a/src/store/data-explorer/data-explorer-middleware-service.ts b/src/store/data-explorer/data-explorer-middleware-service.ts
index 57fd0b59..219e7603 100644
--- a/src/store/data-explorer/data-explorer-middleware-service.ts
+++ b/src/store/data-explorer/data-explorer-middleware-service.ts
@@ -25,7 +25,7 @@ export abstract class DataExplorerMiddlewareService {
         return getDataExplorerColumnFilters(columns, columnName);
     }
 
-    abstract requestItems(api: MiddlewareAPI<Dispatch, RootState>, criteriaChanged?: boolean): void;
+    abstract requestItems(api: MiddlewareAPI<Dispatch, RootState>, criteriaChanged?: boolean): Promise<void>;
 }
 
 export const getDataExplorerColumnFilters = <T>(columns: DataColumns<T>, columnName: string): DataTableFilters => {
diff --git a/src/store/data-explorer/data-explorer-middleware.test.ts b/src/store/data-explorer/data-explorer-middleware.test.ts
index 5d729ce2..4a858c27 100644
--- a/src/store/data-explorer/data-explorer-middleware.test.ts
+++ b/src/store/data-explorer/data-explorer-middleware.test.ts
@@ -202,7 +202,7 @@ class ServiceMock extends DataExplorerMiddlewareService {
     constructor(private config: {
         id: string,
         columns: DataColumns<any>,
-        requestItems: (api: MiddlewareAPI) => void
+        requestItems: (api: MiddlewareAPI) => Promise<void>
     }) {
         super(config.id);
     }
@@ -211,7 +211,8 @@ class ServiceMock extends DataExplorerMiddlewareService {
         return this.config.columns;
     }
 
-    requestItems(api: MiddlewareAPI) {
+    requestItems(api: MiddlewareAPI): Promise<void> {
         this.config.requestItems(api);
+        return Promise.resolve();
     }
 }
diff --git a/src/store/data-explorer/data-explorer-middleware.ts b/src/store/data-explorer/data-explorer-middleware.ts
index e377f341..cc9c1a72 100644
--- a/src/store/data-explorer/data-explorer-middleware.ts
+++ b/src/store/data-explorer/data-explorer-middleware.ts
@@ -3,8 +3,12 @@
 //
 // SPDX-License-Identifier: AGPL-3.0
 
+import { Dispatch } from 'redux';
+import { RootState } from '~/store/store';
+import { ServiceRepository } from '~/services/services';
 import { Middleware } from "redux";
-import { dataExplorerActions, bindDataExplorerActions } from "./data-explorer-action";
+import { dataExplorerActions, bindDataExplorerActions, DataTableRequestState } from "./data-explorer-action";
+import { getDataExplorer } from "./data-explorer-reducer";
 import { DataExplorerMiddlewareService } from "./data-explorer-middleware-service";
 
 export const dataExplorerMiddleware = (service: DataExplorerMiddlewareService): Middleware => api => next => {
@@ -37,7 +41,37 @@ export const dataExplorerMiddleware = (service: DataExplorerMiddlewareService):
                 api.dispatch(actions.REQUEST_ITEMS(true));
             }),
             REQUEST_ITEMS: handleAction(({ criteriaChanged }) => {
-                service.requestItems(api, criteriaChanged);
+                api.dispatch<any>(async (dispatch: Dispatch, getState: () => RootState, services: ServiceRepository) => {
+                    while (true) {
+                        let de = getDataExplorer(getState().dataExplorer, service.getId());
+                        switch (de.requestState) {
+                            case DataTableRequestState.IDLE:
+                                // Start a new request.
+                                try {
+                                    dispatch(actions.SET_REQUEST_STATE({ requestState: DataTableRequestState.PENDING }));
+                                    await service.requestItems(api, criteriaChanged);
+                                } catch {
+                                    dispatch(actions.SET_REQUEST_STATE({ requestState: DataTableRequestState.NEED_REFRESH }));
+                                }
+                                // Now check if the state is still PENDING, if it moved to NEED_REFRESH
+                                // then we need to reissue requestItems
+                                de = getDataExplorer(getState().dataExplorer, service.getId());
+                                const complete = (de.requestState === DataTableRequestState.PENDING);
+                                dispatch(actions.SET_REQUEST_STATE({ requestState: DataTableRequestState.IDLE }));
+                                if (complete) {
+                                    return;
+                                }
+                                break;
+                            case DataTableRequestState.PENDING:
+                                // State is PENDING, move it to NEED_REFRESH so that when the current request finishes it starts a new one.
+                                dispatch(actions.SET_REQUEST_STATE({ requestState: DataTableRequestState.NEED_REFRESH }));
+                                return;
+                            case DataTableRequestState.NEED_REFRESH:
+                                // Nothing to do right now.
+                                return;
+                        }
+                    }
+                });
             }),
             default: () => next(action)
         });
diff --git a/src/store/data-explorer/data-explorer-reducer.ts b/src/store/data-explorer/data-explorer-reducer.ts
index fc7438a5..7705a891 100644
--- a/src/store/data-explorer/data-explorer-reducer.ts
+++ b/src/store/data-explorer/data-explorer-reducer.ts
@@ -8,7 +8,7 @@ import {
     SortDirection,
     toggleSortDirection
 } from "~/components/data-table/data-column";
-import { DataExplorerAction, dataExplorerActions } from "./data-explorer-action";
+import { DataExplorerAction, dataExplorerActions, DataTableRequestState } from "./data-explorer-action";
 import { DataColumns, DataTableFetchMode } from "~/components/data-table/data-table";
 import { DataTableFilters } from "~/components/data-table-filters/data-table-filters-tree";
 
@@ -22,6 +22,7 @@ export interface DataExplorer {
     rowsPerPageOptions: number[];
     searchValue: string;
     working?: boolean;
+    requestState: DataTableRequestState;
 }
 
 export const initialDataExplorer: DataExplorer = {
@@ -32,7 +33,8 @@ export const initialDataExplorer: DataExplorer = {
     page: 0,
     rowsPerPage: 50,
     rowsPerPageOptions: [50, 100, 200, 500],
-    searchValue: ""
+    searchValue: "",
+    requestState: DataTableRequestState.IDLE
 };
 
 export type DataExplorerState = Record<string, DataExplorer>;
@@ -75,6 +77,9 @@ export const dataExplorerReducer = (state: DataExplorerState = {}, action: DataE
         SET_EXPLORER_SEARCH_VALUE: ({ id, searchValue }) =>
             update(state, id, explorer => ({ ...explorer, searchValue })),
 
+        SET_REQUEST_STATE: ({ id, requestState }) =>
+            update(state, id, explorer => ({ ...explorer, requestState })),
+
         TOGGLE_SORT: ({ id, columnName }) =>
             update(state, id, mapColumns(toggleSort(columnName))),
 
diff --git a/src/store/processes/processes-actions.ts b/src/store/processes/processes-actions.ts
index d3d715ad..bb60378c 100644
--- a/src/store/processes/processes-actions.ts
+++ b/src/store/processes/processes-actions.ts
@@ -123,5 +123,3 @@ export const removeProcessPermanently = (uuid: string) =>
         dispatch(projectPanelActions.REQUEST_ITEMS());
         dispatch(snackbarActions.OPEN_SNACKBAR({ message: 'Removed.', hideDuration: 2000, kind: SnackbarKind.SUCCESS }));
     };
-
-
diff --git a/src/websocket/websocket.ts b/src/websocket/websocket.ts
index d1041461..1a5964b5 100644
--- a/src/websocket/websocket.ts
+++ b/src/websocket/websocket.ts
@@ -8,11 +8,12 @@ import { Config } from '~/common/config';
 import { WebSocketService } from './websocket-service';
 import { ResourceEventMessage } from './resource-event-message';
 import { ResourceKind } from '~/models/resource';
-import { loadProcess } from '~/store/processes/processes-actions';
-import { loadContainers } from '~/store/processes/processes-actions';
+// import { loadProcess } from '~/store/processes/processes-actions';
+// import { loadContainers } from '~/store/processes/processes-actions';
 import { LogEventType } from '~/models/log';
 import { addProcessLogsPanelItem } from '../store/process-logs-panel/process-logs-panel-actions';
-import { FilterBuilder } from "~/services/api/filter-builder";
+// import { FilterBuilder } from "~/services/api/filter-builder";
+import { subprocessPanelActions } from "~/store/subprocess-panel/subprocess-panel-actions";
 
 export const initWebSocket = (config: Config, authService: AuthService, store: RootStore) => {
     if (config.websocketUrl) {
@@ -28,15 +29,16 @@ const messageListener = (store: RootStore) => (message: ResourceEventMessage) =>
     if (message.eventType === LogEventType.CREATE || message.eventType === LogEventType.UPDATE) {
         switch (message.objectKind) {
             case ResourceKind.CONTAINER_REQUEST:
-                return store.dispatch(loadProcess(message.objectUuid));
+            // return store.dispatch(loadProcess(message.objectUuid));
             case ResourceKind.CONTAINER:
-                return store.dispatch(loadContainers(
-                    new FilterBuilder().addIn('uuid', [message.objectUuid]).getFilters()
-                ));
+                // return store.dispatch(loadContainers(
+                //     new FilterBuilder().addIn('uuid', [message.objectUuid]).getFilters()
+                // ));
+                store.dispatch(subprocessPanelActions.REQUEST_ITEMS());
             default:
                 return;
         }
     } else {
-        return store.dispatch(addProcessLogsPanelItem(message as ResourceEventMessage<{text: string}>));
+        return store.dispatch(addProcessLogsPanelItem(message as ResourceEventMessage<{ text: string }>));
     }
 };

-----------------------------------------------------------------------


hooks/post-receive
-- 




More information about the arvados-commits mailing list