Skip to content

Commit

Permalink
Merge pull request #177 from xuwenyihust/151-show-last-executed-time-…
Browse files Browse the repository at this point in the history
…for-cell

Refactor notebook code to add new components and fix syntax errors
  • Loading branch information
xuwenyihust authored Jun 9, 2024
2 parents 04c5396 + a8cf093 commit 8a3e54e
Show file tree
Hide file tree
Showing 9 changed files with 74 additions and 30 deletions.
5 changes: 3 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ PawMark is a platform for big data and AI. It is based on Apache Spark and Kuber
<img src="resources/images/architecture.jpg" alt="Architecture">
</p>

## Quick Start
## Setup

### Docker Compose
<details>
Expand Down Expand Up @@ -134,6 +134,7 @@ PawMark is a platform for big data and AI. It is based on Apache Spark and Kuber
| Scala | 2.12 |
| Java | 17 |
| Python | 3.11 |
| IPython | 8.16.1 |
| Apache Spark | 3.5.0 |
| Delta Lake | 3.0.0 |
| Airflow | 2.9.1 |
Expand All @@ -142,7 +143,7 @@ PawMark is a platform for big data and AI. It is based on Apache Spark and Kuber


## License
This project is licensed under the terms of the MIT license.
This project is licensed under the terms of the Apache-2.0 license.

## Reference
- [Running Apache Spark on Kubernetes](https://medium.com/empathyco/running-apache-spark-on-kubernetes-2e64c73d0bb2)
Expand Down
25 changes: 21 additions & 4 deletions examples/notebook.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@
"cells": [
{
"cell_type": "markdown",
"lastExecutionResult": null,
"lastExecutionTime": null,
"metadata": {},
"outputs": [],
"source": [
Expand All @@ -11,27 +13,31 @@
{
"cell_type": "code",
"execution_count": 1,
"lastExecutionResult": "error",
"lastExecutionTime": "2024-06-09 15:24:10",
"metadata": {},
"outputs": [
{
"ename": "NameError",
"evalue": "name 'qwfhbnqjnfjknqw' is not defined",
"evalue": "name 'qegnvoign' is not defined",
"output_type": "error",
"traceback": [
"\u001b[0;31m---------------------------------------------------------------------------\u001b[0m",
"\u001b[0;31mNameError\u001b[0m Traceback (most recent call last)",
"Cell \u001b[0;32mIn[108], line 1\u001b[0m\n\u001b[0;32m----> 1\u001b[0m \u001b[38;5;28mprint\u001b[39m(\u001b[43mqwfhbnqjnfjknqw\u001b[49m) \n",
"\u001b[0;31mNameError\u001b[0m: name 'qwfhbnqjnfjknqw' is not defined"
"Cell \u001b[0;32mIn[182], line 1\u001b[0m\n\u001b[0;32m----> 1\u001b[0m \u001b[38;5;28mprint\u001b[39m(\u001b[43mqegnvoign\u001b[49m) \n",
"\u001b[0;31mNameError\u001b[0m: name 'qegnvoign' is not defined"
]
}
],
"source": [
"print(qwfhbnqjnfjknqw) "
"print(qegnvoign) "
]
},
{
"cell_type": "code",
"execution_count": null,
"lastExecutionResult": "success",
"lastExecutionTime": "2024-06-09 15:24:15",
"metadata": {},
"outputs": [],
"source": [
Expand All @@ -42,6 +48,8 @@
{
"cell_type": "code",
"execution_count": null,
"lastExecutionResult": "success",
"lastExecutionTime": "2024-06-09 15:24:15",
"metadata": {},
"outputs": [
{
Expand All @@ -55,6 +63,15 @@
"source": [
"print(222)"
]
},
{
"cell_type": "code",
"execution_count": null,
"lastExecutionResult": "success",
"lastExecutionTime": "2024-06-09 15:24:15",
"metadata": {},
"outputs": [],
"source": []
}
],
"metadata": {
Expand Down
24 changes: 15 additions & 9 deletions webapp/src/api/notebooks/index.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
import { CellStatus } from "../../components/notebook/cell/CellStatus";
import { OutputType } from '../../components/notebook/cell/result/OutputType';
import { CellExecuteResultType } from "../../components/notebook/cell/CellExecuteResultType";


export const fetchFiles = async (path = '') => {
const url = new URL(path);
Expand Down Expand Up @@ -254,42 +257,45 @@ export const runCell = async (
allow_stdin: false,
},
}));

cell.lastExecutionResult = CellExecuteResultType.SUCCESS;

// Wait for the execute_result message
const result = await new Promise((resolve) => {
socket.onmessage = (event) => {
const message = JSON.parse(event.data);
// console.log('Received message:', message);
// Only process messages that are in response to this execution
if (message.parent_header.msg_id === msg_id) {
if (message.header.msg_type === 'status') {
console.log('Received message:', message);
cell.lastExecutionTime = new Date().toISOString().slice(0, 19).replace('T', ' ');
if (message.header.msg_type === OutputType.STATUS) {
// Update the cell's status
console.log('Cell status:', message.content.execution_state);
setCellStatus(message.content.execution_state);
// If the kernel is idle, resolve the promise
if (message.content.execution_state === CellStatus.IDLE) {
resolve(cell.outputs);
}
}
else if (message.header.msg_type === 'stream') {
else if (message.header.msg_type === OutputType.STREAM) {
// Add the output to the cell's outputs array
cell.outputs.push({
output_type: 'stream',
output_type: OutputType.STREAM,
name: message.content.name,
text: message.content.text,
});
} else if (message.header.msg_type === 'execute_result') {
} else if (message.header.msg_type === OutputType.EXECUTE_RESULT) {
// Add the output to the cell's outputs array
cell.outputs.push({
output_type: 'execute_result',
output_type: OutputType.EXECUTE_RESULT,
data: message.content.data,
execution_count: message.content.execution_count,
metadata: message.content.metadata,
});
} else if (message.header.msg_type === 'error') {
} else if (message.header.msg_type === OutputType.ERROR) {
cell.lastExecutionResult = CellExecuteResultType.ERROR;
// Add the output to the cell's outputs array
cell.outputs.push({
output_type: 'error',
output_type: OutputType.ERROR,
ename: message.content.ename,
evalue: message.content.evalue,
traceback: message.content.traceback,
Expand Down
17 changes: 14 additions & 3 deletions webapp/src/components/notebook/Notebook.js
Original file line number Diff line number Diff line change
Expand Up @@ -43,15 +43,17 @@ function Notebook({

useEffect(() => {
if (notebook && notebook.content) {
const notebookContentWithExecutionFlag = notebook.content.cells.map(cell => ({
const notebookContentWithCustomFields = notebook.content.cells.map(cell => ({
...cell,
isExecuted: cell.cell_type === 'code' ? false : cell.cell_type === 'markdown' ? true : cell.isExecuted,
lastExecutionResult: null,
lastExecutionTime: null,
}));
setNotebookState({
...notebook,
content: {
...notebook.content,
cells: notebookContentWithExecutionFlag,
cells: notebookContentWithCustomFields,
}
});
setCurrentName(notebook.name);
Expand Down Expand Up @@ -239,7 +241,16 @@ function Notebook({
handleClickNotebookName={handleClickNotebookName}
handleChangeNotebookName={handleChangeNotebookName}
handleSaveNotebookName={handleSaveNotebookName}
runAllCells={runAllCells}
runAllCells={
() => runAllCells(
jupyterBaseUrl,
notebookState,
kernelId,
setKernelId,
cellStatuses,
setCellStatus,
cellExecutedStatuses,
setCellExecutedStatus)}
saveNotebook={handleUpdateNotebook}
deleteNotebook={handleDeleteNotebook}/>
}
Expand Down
10 changes: 1 addition & 9 deletions webapp/src/components/notebook/NotebookToolbar.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,6 @@ import Tooltip from '@mui/material/Tooltip';
import { Box, AppBar, Toolbar, Typography, IconButton } from '@mui/material';

function NotebookToolbar({
jupyterBaseUrl,
notebook,
kernelId,
setKernelId,
cellStatuses,
setCellStatus,
cellExecutedStatuses,
setCellExecutedStatus,
isNameEditing,
currentName,
isNotebookModified,
Expand Down Expand Up @@ -99,7 +91,7 @@ function NotebookToolbar({
<IconButton
disableRipple
onClick={() =>
runAllCells(jupyterBaseUrl, notebook, kernelId, setKernelId, cellStatuses, setCellStatus, cellExecutedStatuses, setCellExecutedStatus)}
runAllCells()}
aria-label="run"
sx={{
width: 'auto',
Expand Down
2 changes: 1 addition & 1 deletion webapp/src/components/notebook/cell/Cell.js
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ function Cell({
marginBottom: 1,
marginLeft: 10,
marginRight: 1,
border: isFocused ? 0.8 : 0.5,
border: isFocused ? 1.0 : 0.5,
borderColor: isFocused ? 'black' : 'lightgrey',
backgroundColor: 'rgba(0, 0, 0, 0.03)',
}}>
Expand Down
4 changes: 4 additions & 0 deletions webapp/src/components/notebook/cell/CellExecuteResultType.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
export const CellExecuteResultType = {
ERROR: 'error',
SUCCESS: 'success',
}
16 changes: 14 additions & 2 deletions webapp/src/components/notebook/cell/header/CellHeader.js
Original file line number Diff line number Diff line change
@@ -1,15 +1,16 @@
import { Box, Typography, CardHeader, CircularProgress } from '@mui/material';
import { CgCheck, CgDanger } from "react-icons/cg";
import { CellStatus } from '../CellStatus';
import RunButton from './RunButton';
import TypeSelect from './TypeSelect';
import MoreButton from './MoreButton';
import { CellExecuteResultType } from '../CellExecuteResultType';


function CellHeader({
cell,
index,
cellStatus,
setCellExecutedStatus,
handleRunCell,
handleChangeCellType,
handleCopyCell,
Expand All @@ -29,12 +30,23 @@ function CellHeader({
handleRunCell={handleRunCell}/>
} { (cellStatus === CellStatus.BUSY ||
cellStatus === CellStatus.INITIALIZING ||
cellStatus === CellStatus.WAITING) &&
cellStatus === CellStatus.WAITING) ?
<Typography
variant="body2"
style={{ marginLeft: 10 }}
color="textSecondary">
{cellStatus}
</Typography> :
cell.lastExecutionResult === null ? null :
(cell.lastExecutionResult === CellExecuteResultType.SUCCESS ?
<CgCheck style={{ color: 'green', marginLeft: 10 }}/> :
<CgDanger size={16} style={{ color: 'red', marginLeft: 10 }}/>)}
{cellStatus === CellStatus.IDLE &&
<Typography
variant="body2"
color="textSecondary"
style={{ marginLeft: 10 }}>
{cell.lastExecutionTime}
</Typography>}
</Box>
<Box display="flex" justifyContent="flex-end">
Expand Down
1 change: 1 addition & 0 deletions webapp/src/components/notebook/cell/result/OutputType.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,5 @@ export const OutputType = {
EXECUTE_RESULT: 'execute_result',
ERROR: 'error',
STREAM: 'stream',
STATUS: 'status',
};

0 comments on commit 8a3e54e

Please sign in to comment.