Skip to content

Commit 82838fe

Browse files
committed
Merge branch 'rebase-in-time'
2 parents b312716 + d2b1366 commit 82838fe

File tree

25 files changed

+328
-74
lines changed

25 files changed

+328
-74
lines changed

Dockerfile

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
FROM node:21.3.0 as base
1+
FROM node:21.3.0 AS base
22
ENV PUPPETEER_SKIP_CHROMIUM_DOWNLOAD true
33
RUN echo "Installing system dependencies (git+puppeteer deps)..." \
44
&& apt-get update \
@@ -16,32 +16,32 @@ RUN npm i -g ts-node
1616
USER node
1717
WORKDIR /app
1818

19-
FROM base as prepare_system
19+
FROM base AS prepare_system
2020
USER root
2121
RUN echo "Installing system deps..." && apt-get -y update && apt-get -y install r-base python3-dev python3-pip python3-venv pkg-config libhdf5-dev && rm -rf /var/lib/apt/lists/*
2222
ENV PYTHON_BIN="python3"
2323
USER node
2424

25-
FROM prepare_system as prepare_r
25+
FROM prepare_system AS prepare_r
2626
USER root
2727
COPY --chown=node:node cli/setup.R /app/setup.R
2828
RUN echo "Running setup.R..." && R -e "source('/app/setup.R')" && rm /app/setup.R
2929
USER node
3030

31-
FROM base as prepare_src
31+
FROM base AS prepare_src
3232
COPY --chown=node:node . /app
3333

34-
FROM prepare_src as prepare_package_json
34+
FROM prepare_src AS prepare_package_json
3535
RUN find /app -type d -name "node_modules" -exec rm -rf {} + \
3636
&& find /app -type f -a \! \( -name "package.json" -o -name "package-lock.json" -o -name ".puppeteerrc.cjs" \) -delete \
3737
&& find /app -type d -empty -delete
3838

39-
FROM prepare_src as prepare_requirements_txt
39+
FROM prepare_src AS prepare_requirements_txt
4040
RUN find /app -type d -name "node_modules" -exec rm -rf {} + \
4141
&& find /app -type f -a \! \( -name "requirements.txt" -o -name "enumerate-requirements.ts" \) -delete \
4242
&& find /app -type d -empty -delete
4343

44-
FROM base as prepare_npm_i
44+
FROM base AS prepare_npm_i
4545
COPY --from=prepare_package_json /app /app
4646
RUN echo "Installing NodeJS dependencies..." && npm i
4747

@@ -56,18 +56,18 @@ RUN mv /app/requirements.txt /tmp/requirements.txt \
5656
&& chown node:node /app/requirements.txt
5757
USER node
5858

59-
FROM prepare_src as prepare_build
59+
FROM prepare_src AS prepare_build
6060
COPY --from=prepare_npm_i /app /app
6161
RUN echo "Building app..." && LANDING_PAGE=/graph/extend PUBLIC_URL=https://playbook-workflow-builder.cloud npm run build
6262

63-
FROM prepare_system as prepare_python
63+
FROM prepare_system AS prepare_python
6464
COPY --from=prepare_requirements_txt_complete /app /app
6565
USER root
6666
RUN echo "Installing python dependencies..." && python3 -m pip install --break-system-packages -r /app/requirements.txt && rm /app/requirements.txt
6767
USER node
6868

6969
# TARGET: dev -- development environment with dependencies to run dev tools
70-
FROM prepare_system as dev
70+
FROM prepare_system AS dev
7171
USER root
7272
RUN echo "Installing dev deps..." \
7373
&& apt-get -y update \
@@ -98,13 +98,13 @@ COPY --from=prepare_python /usr/local/lib/ /usr/local/lib/
9898
CMD ["/bin/bash"]
9999

100100
# TARGET: app_minimal -- production server with dependencies to run just the webserver
101-
FROM base as app_minimal
101+
FROM base AS app_minimal
102102
COPY --from=prepare_build /app /app
103103
ENV PORT 3000
104104
CMD ["npm", "run", "start"]
105105

106106
# TARGET: app -- production server with dependencies to run everything
107-
FROM prepare_system as app
107+
FROM prepare_system AS app
108108
COPY --from=prepare_r /usr/local/lib/ /usr/local/lib/
109109
COPY --from=prepare_python /usr/local/lib/ /usr/local/lib/
110110
COPY --from=prepare_build /app /app

app/api/v1/user/playbooks/index.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -229,6 +229,9 @@ export const UpdateUserPlaybook = API.post('/api/v1/user/playbooks/[id]/update')
229229
)
230230
if (fpl === undefined) throw new NotFoundError()
231231
fpl = fpl.rebasePlaybookMetadata(fpl, await fpprg.resolvePlaybookMetadata(inputs.body.playbook_metadata)).head
232+
fpl = await fpprg.upsertFPL(fpl)
233+
if (fpl === undefined) throw new NotFoundError()
234+
fpl = await fpl.rebaseInTime()
232235
if (fpl === undefined) throw new NotFoundError()
233236
fpl = await fpprg.upsertFPL(fpl)
234237
const session = await getServerSessionWithId(req, res)

app/fragments/graph/catalog.tsx

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ const InputGroup = dynamic(() => import('@blueprintjs/core').then(({ InputGroup
1010

1111
type KVCounts = { [key: string]: { [val: string]: number } }
1212

13-
export default function Catalog<T extends { spec: string, meta?: { pagerank?: number, tags?: Record<string, Record<string, number>> } }>({ items, weights, serialize, children }: {
13+
export default function Catalog<T extends { spec: string, meta?: { pagerank?: number, tags?: Record<string, Record<string, number>>, external?: boolean } }>({ items, weights, serialize, children }: {
1414
items: Array<T>,
1515
weights: Record<string, number>,
1616
serialize: (item: T) => string,
@@ -27,6 +27,7 @@ export default function Catalog<T extends { spec: string, meta?: { pagerank?: nu
2727
for (const k in items) {
2828
const item = items[k]
2929
const item_meta = item.meta||{}
30+
item_meta.tags = item_meta.tags||{}
3031
item_search_ts[k] = tsvector(serialize(item))
3132
pagerank_max = Math.max(item_meta.pagerank||0, pagerank_max)
3233
weight_max = Math.max(weights[item.spec]||0, weight_max)

app/fragments/graph/cell.tsx

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,13 +3,16 @@ import type KRG from '@/core/KRG'
33
import dynamic from 'next/dynamic'
44
import { Metapath, useMetapathOutput } from '@/app/fragments/metapath'
55
import Head from 'next/head'
6+
import { useRouter } from 'next/router'
67
import { useStory } from '@/app/fragments/story'
78
import SafeRender from '@/utils/saferender'
89
import { Abstract, FigureCaption, Methods, References } from './story'
10+
import { z } from 'zod'
911

1012
const Prompt = dynamic(() => import('@/app/fragments/graph/prompt'))
1113

1214
export default function Cell({ session_id, krg, id, head, metapath }: { session_id?: string, krg: KRG, id: string, head: Metapath, metapath: Metapath[] }) {
15+
const router = useRouter()
1316
const processNode = krg.getProcessNode(head.process.type)
1417
const { data: { output, outputNode }, status, error: outputError, mutate } = useMetapathOutput({ krg, head })
1518
const story = useStory()
@@ -52,11 +55,13 @@ export default function Cell({ session_id, krg, id, head, metapath }: { session_
5255
: <SafeRender component={outputNode.view} props={output} />}
5356
<FigureCaption id={head.id} story={{ ...story, ast: astFiltered }} />
5457
<References story={{ ...story, ast: astFiltered }} />
58+
{head.process.timestamp ? <div className="alert alert-info">Saved computation from {new Date(head.process.timestamp).toLocaleString()}</div> : null}
5559
<button
5660
className="btn btn-primary"
5761
onClick={async (evt) => {
58-
const req = await fetch(`${session_id ? `/api/socket/${session_id}` : ''}/api/db/process/${head.process.id}/output/delete`, { method: 'POST' })
59-
const res = await req.text()
62+
const req = await fetch(`${session_id ? `/api/socket/${session_id}` : ''}/api/db/fpl/${id}/recompute/${head.id}`, { method: 'POST' })
63+
const res = z.object({ head: z.string(), rebased: z.string() }).parse(await req.json())
64+
router.push(`${session_id ? `/session/${session_id}` : ''}/graph/${res.head}${res.head !== res.rebased ? `/node/${res.rebased}` : ''}`, undefined, { shallow: true })
6065
mutate()
6166
}}
6267
>Recompute</button>

app/fragments/graph/extend.tsx

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,9 @@ export default function Extend({ session_id, krg, id, head, metapath }: { sessio
4848
</Head>
4949
<Catalog<ProcessMetaNode & ({}|{ onClick: (_: { router: NextRouter, id: string, head: Metapath }) => void })>
5050
items={[
51-
...krg.getNextProcess(processNode ? processNode.output.spec : '').filter(proc => proc.meta.hidden !== true),
51+
...krg.getNextProcess(processNode ? processNode.output.spec : '')
52+
.filter(proc => proc.meta.hidden !== true)
53+
.map(proc => ({ ...proc, meta: { ...proc.meta, tags: { ...(proc.meta.tags??{}), External: { [proc.meta.external ? 'True': 'False']: 1 } } } })),
5254
...SuggestionEdges(processNode ? processNode.output : undefined),
5355
]}
5456
serialize={item => [
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
import fpprg from '@/app/fpprg'
2+
import { z } from 'zod'
3+
import { Process } from '@/core/FPPRG'
4+
import handler from '@/utils/next-rest'
5+
import { NotFoundError, UnsupportedMethodError } from '@/spec/error'
6+
7+
const QueryType = z.object({
8+
fpl_id: z.string(),
9+
rebase_id: z.string(),
10+
})
11+
12+
export default handler(async (req, res) => {
13+
if (req.method !== 'POST') throw new UnsupportedMethodError(req.method)
14+
const { fpl_id, rebase_id } = QueryType.parse(req.query)
15+
const rebase = await fpprg.getFPL(rebase_id)
16+
if (rebase === undefined) throw new NotFoundError()
17+
const old_process = rebase.process
18+
const old_fpl = await fpprg.getFPL(fpl_id)
19+
if (old_fpl === undefined) throw new NotFoundError()
20+
if (old_process.timestamp !== undefined) {
21+
const new_process = await fpprg.upsertProcess(new Process(
22+
old_process.type,
23+
old_process.data,
24+
old_process.inputs,
25+
))
26+
const { rebased, head } = old_fpl.rebase(old_process, new_process)
27+
const fpl = await fpprg.upsertFPL(head)
28+
res.status(200).json({ head: fpl.id, rebased: rebased.id })
29+
} else {
30+
const resolved = await fpprg.getResolved(old_process.id)
31+
if (resolved === undefined) throw new NotFoundError()
32+
await fpprg.deleteResolved(resolved)
33+
res.status(200).json({ head: fpl_id, rebased: rebase_id })
34+
}
35+
})

app/public/playbooksDemo.ts

Lines changed: 12 additions & 9 deletions
Large diffs are not rendered by default.

components/MW/metgene_summary/index.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ export const MetGeneSearch = MetaNode('MetGeneSearch')
3232
description: 'Identify gene-centric information from Metabolomics.',
3333
icon: [metgene_icon],
3434
pagerank: 2,
35+
external: true,
3536
})
3637
.inputs({ gene: GeneTerm })
3738
.output(MetGeneSummary)

components/data/limma_voom/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"name": "limma_voom",
33
"version": "1.0.0",
4-
"license": "CC-BY-4.0",
4+
"license": "GPL-2.0-or-later",
55
"author": "Alex Agris <aagris@stanford.edu>",
66
"private": true,
77
"dependencies": {

components/data/pca_transformation/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"name": "pca-transformation",
33
"version": "1.0.0",
4-
"license": "CC-BY-4.0",
4+
"license": "GPL-3.0-or-later",
55
"author": "Juncheng Pan <pan_juncheng@yahoo.com>",
66
"private": true,
77
"dependencies": {

0 commit comments

Comments
 (0)