From 28d6f1bacad87254d0e954a2c0df966cfd31668c Mon Sep 17 00:00:00 2001 From: Simone Bembi Date: Thu, 18 Jan 2024 19:43:28 +0000 Subject: [PATCH] fix: failing session page needed advanced terminal too --- client/common/api/session.ts | 4 +- client/common/state/models/failures-model.ts | 6 ++- client/common/state/models/session-model.ts | 2 +- .../components/session/failing-session.scss | 9 +++++ .../components/session/failing-session.tsx | 38 +++++++++++-------- .../session/session-retrieval-hook.ts | 4 +- .../session/session-terminal-container.tsx | 9 +++-- .../src/components/session/session.tsx | 1 - pkg/http/rest/rest-handler.go | 2 +- pkg/services/query-service.go | 13 ++++++- pkg/storage/session-storage.go | 11 ++++++ 11 files changed, 70 insertions(+), 29 deletions(-) create mode 100644 client/manager/src/components/session/failing-session.scss diff --git a/client/common/api/session.ts b/client/common/api/session.ts index 15bfc24..46bf444 100644 --- a/client/common/api/session.ts +++ b/client/common/api/session.ts @@ -3,9 +3,7 @@ import { SessionStatus, SessionKillReason } from '../state/models/session-model- import Axios from 'axios'; import { buildRequest } from './common'; -export interface IAPISession extends Omit { - logs: ISessionLog[]; -} +export interface IAPISession extends ISession {} export interface IAPISessionLogsAndStatus { logs: ISessionLog[]; diff --git a/client/common/state/models/failures-model.ts b/client/common/state/models/failures-model.ts index 3cbb3cc..4199c90 100644 --- a/client/common/state/models/failures-model.ts +++ b/client/common/state/models/failures-model.ts @@ -3,7 +3,7 @@ import { APIPayload, APIRequestResult } from "@polo/common/api/common"; import { values } from "mobx"; import { flow, getParent, hasParent, types } from "mobx-state-tree"; import { IApp, SessionSubscriptionEventType } from "."; -import { ISession, ISessionLog, SessionModel } from "./session-model"; +import { ISession, ISessionLog, SessionModel, castAPISessionToSessionModel } from "./session-model"; export enum FailureStatus { ACK = 'acknowledged', @@ -19,6 +19,7 @@ export type TFailuresDictionary = { }; export const FailuresModel = types.model({ + currentSession: types.maybeNull(SessionModel), acknowledged : types.map(SessionModel), unacknowledged: types.map(SessionModel), }) @@ -49,6 +50,9 @@ export const FailuresModel = types.model({ const retrieveFailedSession = flow(function* retrieveFailedSession(uuid: string, markAsSeen = true) { const request: APIPayload = yield retrieveFailedSessionAPI(uuid); if (markAsSeen) markFailedSessionAsAcknowledged(uuid); + if (request.result === APIRequestResult.SUCCEEDED) { + self.currentSession = castAPISessionToSessionModel(request.payload); + } return request; }); diff --git a/client/common/state/models/session-model.ts b/client/common/state/models/session-model.ts index 66c6b32..1c83138 100644 --- a/client/common/state/models/session-model.ts +++ b/client/common/state/models/session-model.ts @@ -58,7 +58,7 @@ export const castAPISessionToSessionModel = (apiSession: IAPISession): ISession const { logs, ...rest } = apiSession; const session = rest as ISession; if (logs) { - session.logs = logs.reduce<{ [k: string]: ISessionLog }>((acc, log) => { + session.logs = Array.from(logs.values()).reduce<{ [k: string]: ISessionLog }>((acc, log) => { acc[log.uuid] = log; return acc; }, {}) as any; diff --git a/client/manager/src/components/session/failing-session.scss b/client/manager/src/components/session/failing-session.scss new file mode 100644 index 0000000..d314032 --- /dev/null +++ b/client/manager/src/components/session/failing-session.scss @@ -0,0 +1,9 @@ +@import "@polo/common/styles/index"; + +.xterm-rows { + @apply m-3; +} + +.xterm-cursor { + display: none !important; +} \ No newline at end of file diff --git a/client/manager/src/components/session/failing-session.tsx b/client/manager/src/components/session/failing-session.tsx index 1ba164c..52baec0 100644 --- a/client/manager/src/components/session/failing-session.tsx +++ b/client/manager/src/components/session/failing-session.tsx @@ -1,6 +1,6 @@ import { APIRequestResult } from '@polo/common/api/common'; import { IApp } from '@polo/common/state/models/app-model'; -import { ISession, ISessionLog } from '@polo/common/state/models/session-model'; +import { ISession, ISessionLog, castAPISessionToSessionModel } from '@polo/common/state/models/session-model'; import dayjs from 'dayjs'; import { values } from 'mobx'; import { observer } from 'mobx-react-lite'; @@ -9,6 +9,10 @@ import { useHistory } from 'react-router-dom'; import { CommitMessage } from '../shared/commit-message'; import { SessionLogs } from './session-logs'; import { useSessionRetrieval } from './session-retrieval-hook'; +import { SessionTerminalContainer } from './session-terminal-container'; +import '@polo/manager/src/components/session/failing-session.scss'; + +const useAdvancedTerminal = window.configuration.advancedTerminalOutput; type TProps = { app: IApp; @@ -32,30 +36,34 @@ export const FailingSession = observer((props: TProps) => { props.app.failures.retrieveFailedSession(props.uuid), props.app.failures.retrieveFailedSessionLogs(props.uuid) ]) - .then(([sessionResponse, logsResponse]) => { - if (sessionResponse.result === APIRequestResult.FAILED) { - return history.push(`/_polo_`); - } - setSession(sessionResponse.payload); - if (logsResponse.result === APIRequestResult.SUCCEEDED) - setLogs(logsResponse.payload); - }) + .then(([sessionResponse, logsResponse]) => { + if (sessionResponse.result === APIRequestResult.FAILED) { + return history.push(`/_polo_`); + } + const session = castAPISessionToSessionModel(sessionResponse.payload); + setSession(session); + if (logsResponse.result === APIRequestResult.SUCCEEDED) + setLogs(logsResponse.payload); + }) }, [props.uuid]); - if (!session) return null; + if (!props.app.failures.currentSession) return null; return
-

Failing session

+

+ Failing session +

- {session.displayName} + {props.app.failures.currentSession.displayName}
- - + {useAdvancedTerminal && } + {!useAdvancedTerminal && + onLogsProportionChanged={setOverlayProportions} />}
}); diff --git a/client/manager/src/components/session/session-retrieval-hook.ts b/client/manager/src/components/session/session-retrieval-hook.ts index 193adc1..d264a27 100644 --- a/client/manager/src/components/session/session-retrieval-hook.ts +++ b/client/manager/src/components/session/session-retrieval-hook.ts @@ -75,7 +75,7 @@ export const useSessionTerminalRetrieval = ( session: ISession, container: React.MutableRefObject, retrieveFailedSession: (uuid: string) => Promise>, - onSessionFail: () => void, + onSessionFail?: () => void, ) => { const interval = useRef(null); const history = useHistory(); @@ -105,7 +105,7 @@ export const useSessionTerminalRetrieval = ( const failedSessionRequest = await retrieveFailedSession(session.uuid); if (failedSessionRequest.result === APIRequestResult.SUCCEEDED) { redirectToDashboard = false; - onSessionFail(); + onSessionFail?.(); } } catch (e) { console.error(e); diff --git a/client/manager/src/components/session/session-terminal-container.tsx b/client/manager/src/components/session/session-terminal-container.tsx index 0ec025b..0a8d273 100644 --- a/client/manager/src/components/session/session-terminal-container.tsx +++ b/client/manager/src/components/session/session-terminal-container.tsx @@ -1,12 +1,13 @@ -import {useSessionTerminalRetrieval} from '@/components/session/session-retrieval-hook'; -import {IApp, ISession} from '@polo/common/state/models'; -import {observer} from 'mobx-react-lite'; +import { useSessionTerminalRetrieval } from '@/components/session/session-retrieval-hook'; +import { IApp, ISession } from '@polo/common/state/models'; +import { observer } from 'mobx-react-lite'; import React from 'react'; +import 'xterm/css/xterm.css'; type TProps = { app: IApp; session: ISession; - onSessionFail: () => void; + onSessionFail?: () => void; }; export const SessionTerminalContainer = observer((props: TProps) => { diff --git a/client/manager/src/components/session/session.tsx b/client/manager/src/components/session/session.tsx index 38f0454..1086b31 100644 --- a/client/manager/src/components/session/session.tsx +++ b/client/manager/src/components/session/session.tsx @@ -8,7 +8,6 @@ import { observer } from 'mobx-react-lite'; import React, { useEffect, useState } from 'react'; import { useHistory } from 'react-router-dom'; import { CommitMessage } from '../shared/commit-message'; -import 'xterm/css/xterm.css'; import '@polo/manager/src/components/session/session.scss'; import { SessionIntegrationsStatus } from './integrations-status/session-integrations-status'; diff --git a/pkg/http/rest/rest-handler.go b/pkg/http/rest/rest-handler.go index fed3f1e..30d7dae 100644 --- a/pkg/http/rest/rest-handler.go +++ b/pkg/http/rest/rest-handler.go @@ -202,7 +202,6 @@ func (h *Handler) getSessionPTY(query *services.QueryService, logger logging.Log return func(w http.ResponseWriter, r *http.Request, p httprouter.Params) { uuid := p.ByName("uuid") tty, _, err := query.GetSessionTTY(uuid) - defer tty.Close() if err != nil { logger.Error("Error retrieving session TTY: %s", err) @@ -212,6 +211,7 @@ func (h *Handler) getSessionPTY(query *services.QueryService, logger logging.Log w.Write(c) return } + defer tty.Close() if _, err := tty.Seek(0, io.SeekStart); err != nil { logger.Error("Error seeking TTY output: %s\n", err) diff --git a/pkg/services/query-service.go b/pkg/services/query-service.go index 064db8f..de84b2c 100644 --- a/pkg/services/query-service.go +++ b/pkg/services/query-service.go @@ -38,6 +38,17 @@ func (s *QueryService) GetAllAliveSessions() []*models.Session { return s.sessionStorage.GetAllAliveSessions() } +// GetSession returns a session by its UUID, undependently from its status +func (s *QueryService) GetSession(uuid string) *models.Session { + var foundSession *models.Session + for _, session := range s.sessionStorage.GetAll() { + if session.UUID == uuid { + foundSession = session + } + } + return foundSession +} + func (s *QueryService) GetAliveSession(uuid string) *models.Session { var foundSession *models.Session for _, session := range s.sessionStorage.GetAllAliveSessions() { @@ -98,7 +109,7 @@ func (s *QueryService) GetSessionLogsAndStatus(uuid string, lastLogUUID string) } func (s *QueryService) GetSessionTTY(uuid string) (utils.TTY, models.SessionStatus, error) { - session := s.GetAliveSession(uuid) + session := s.GetSession(uuid) if session == nil { return nil, models.SessionStatusStarting, ErrSessionNotFound } diff --git a/pkg/storage/session-storage.go b/pkg/storage/session-storage.go index 9caf17c..d019fc2 100644 --- a/pkg/storage/session-storage.go +++ b/pkg/storage/session-storage.go @@ -170,6 +170,17 @@ func (s *Session) GetByUUID(uuid string) *models.Session { return foundSession } +// GetAll retrieves all sessions +func (s *Session) GetAll() []*models.Session { + s.log.Trace("Getting all alive sessions") + s.RLock() + filteredSessions := make([]*models.Session, 0, len(s.sessions)) + sessions := s.sessions + s.RUnlock() + filteredSessions = append(filteredSessions, sessions...) + return filteredSessions +} + // GetAllAliveSessions retrieves a slice of sessions whose status is "alive". // A session is "alive" if it can or is about to ready for being used func (s *Session) GetAllAliveSessions() []*models.Session {