Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[feat] Add find() method to Container and Sequence types #2959

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 10 additions & 8 deletions pkgs/aimstack/asp/boards/run.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,18 @@

c_hash = session_state.get('container_hash')

runs = None if c_hash is None else Run.filter(f'c.hash=="{c_hash}"')
run = None

if runs is None:
ui.subheader('No runs found')
if c_hash is None:
ui.subheader('No run selected')
ui.board_link('runs.py', 'Explore runs')
run = None
else:
run = runs[0]
hash = run.get('hash')
ui.subheader(f'Run: {hash}')
run = Run.find(c_hash)
if run:
hash = run.get('hash')
ui.subheader(f'Run: {hash}')
else:
ui.subheader('Run not found')
ui.board_link('runs.py', 'Explore runs')


@memoize
Expand Down
64 changes: 60 additions & 4 deletions src/aimcore/web/api/queries/views.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import json

from fastapi.responses import StreamingResponse
from fastapi import Depends, HTTPException

Expand Down Expand Up @@ -37,13 +39,35 @@ async def sequence_search_result_streamer(repo: 'Repo',
yield collect_streamable_data(encoded_tree)


async def sequence_data_streamer(repo: 'Repo',
sequence: Sequence,
p: Optional[int],
start: Optional[int],
stop: Optional[int],
sample_seed: str):
if sequence is None:
return
seq_data = {hash(sequence): sequence_data(
repo, sequence, p, start, stop, sample_seed)}
encoded_tree = encode_tree(seq_data)
yield collect_streamable_data(encoded_tree)


async def container_search_result_streamer(query_collection: Iterable[Container]):
for container in query_collection:
cont_data = {container.hash: container_data(container)}
encoded_tree = encode_tree(cont_data)
yield collect_streamable_data(encoded_tree)


async def container_data_streamer(container: Container):
if container is None:
return
cont_data = {container.hash: container_data(container)}
encoded_tree = encode_tree(cont_data)
yield collect_streamable_data(encoded_tree)


def sequence_query_grouped_response(repo: 'Repo',
query_collection,
p: Optional[int],
Expand Down Expand Up @@ -95,6 +119,40 @@ async def data_fetch_api(type_: str,
return StreamingResponse(streamer)


@query_router.get('/find-container/')
async def find_container_api(type_: str,
hash_: str,
package=Depends(get_root_package)):
repo = get_project_repo()
if type_ not in Container.registry:
raise HTTPException(status_code=400, detail=f'\'{type_}\' is not a valid Container type.')
cont_type = Container.registry[type_][0]
container = cont_type.find(hash_)

streamer = container_data_streamer(container)
return StreamingResponse(streamer)


@query_router.get('/find-sequence/')
async def find_sequence_api(type_: str,
hash_: str,
name: str,
ctx: str,
p: Optional[int] = 500,
start: Optional[int] = None,
stop: Optional[int] = None,
package=Depends(get_root_package)):
repo = get_project_repo()
context = json.loads(ctx)
if type_ not in Sequence.registry:
raise HTTPException(status_code=400, detail=f'\'{type_}\' is not a valid Sequence type.')
seq_type = Sequence.registry[type_][0]
sequence = seq_type.find(hash_, name, context)
sample_seed = f'{hash_}_{name}_{context}'
streamer = sequence_data_streamer(repo, sequence, p, start, stop, sample_seed)
return StreamingResponse(streamer)


@query_router.get('/grouped-sequences/')
async def grouped_data_fetch_api(seq_type: Optional[str] = 'Sequence',
cont_type: Optional[str] = 'Container',
Expand All @@ -106,11 +164,9 @@ async def grouped_data_fetch_api(seq_type: Optional[str] = 'Sequence',
repo = get_project_repo()
query = checked_query(q)
if seq_type not in Sequence.registry:
raise HTTPException(
status_code=400, detail=f'\'{seq_type}\' is not a valid Sequence type.')
raise HTTPException(status_code=400, detail=f'\'{seq_type}\' is not a valid Sequence type.')
if cont_type not in Container.registry:
raise HTTPException(
status_code=400, detail=f'\'{cont_type}\' is not a valid Container type.')
raise HTTPException(status_code=400, detail=f'\'{cont_type}\' is not a valid Container type.')
if query:
query = f'(container.type.startswith("{Container.registry[cont_type][0].get_full_typename()}")) and {query}'
else:
Expand Down
31 changes: 30 additions & 1 deletion src/aimcore/web/ui/public/aim_ui_core.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
# Bindings for fetching Aim Objects
####################

from js import search, runFunction
from js import search, runFunction, findItem
import json
import hashlib

Expand Down Expand Up @@ -90,16 +90,45 @@ def run_function(func_name, params):
raise e


def find_item(type_, is_sequence=False, hash_=None, name=None, ctx=None):
if ctx is not None:
ctx = json.dumps(ctx)

query_key = f"{type_}_{hash_}_{name}_{ctx}"

if query_key in query_results_cache:
return query_results_cache[query_key]

try:
data = findItem(board_path, type_, is_sequence, hash_, name, ctx)
data = json.loads(data)

query_results_cache[query_key] = data
return data
except Exception as e:
if "WAIT_FOR_QUERY_RESULT" in str(e):
raise WaitForQueryError()
else:
raise e

class Sequence:
@classmethod
def filter(self, query="", count=None, start=None, stop=None):
return query_filter("Sequence", query, count, start, stop, is_sequence=True)

@classmethod
def find(self, hash_, name, context):
return find_item("Sequence", is_sequence=True, hash_=hash_, name=name, ctx=context)


class Container:
@classmethod
def filter(self, query=""):
return query_filter("Container", query, None, None, None, is_sequence=False)

@classmethod
def find(self, hash_):
return find_item("Container", is_sequence=False, hash_=hash_)


####################
Expand Down
37 changes: 33 additions & 4 deletions src/aimcore/web/ui/src/modules/core/api/dataFetchApi/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ function createFetchDataRequest(): RequestInstance {

async function call(queryParams: any): Promise<any> {
return (
await api.makeAPIGetRequest(`${ENDPOINTS.DATA.FETCH}`, {
await api.makeAPIGetRequest(ENDPOINTS.DATA.FETCH, {
query_params: queryParams,
signal,
})
Expand Down Expand Up @@ -43,7 +43,7 @@ function createFetchGroupedSequencesRequest(
queryParams: GroupedSequencesSearchQueryParams,
): Promise<ReadableStream> {
return (
await api.makeAPIGetRequest(`${ENDPOINTS.DATA.GET_GROUPED_SEQUENCES}`, {
await api.makeAPIGetRequest(ENDPOINTS.DATA.GET_GROUPED_SEQUENCES, {
query_params: {
seq_type: sequenceType,
cont_type,
Expand Down Expand Up @@ -72,7 +72,7 @@ function createRunFunctionRequest(): RequestInstance {
func_name: string,
request_data: Record<string, any>,
): Promise<any> {
return await api.makeAPIPostRequest(`${ENDPOINTS.DATA.RUN}`, {
return await api.makeAPIPostRequest(ENDPOINTS.DATA.RUN, {
query_params: {
func_name,
},
Expand All @@ -97,7 +97,7 @@ function createBlobsRequest(): RequestInstance {

async function call(uris: string[]): Promise<any> {
return (
await api.makeAPIPostRequest(`${ENDPOINTS.DATA.FETCH_BLOBS}`, {
await api.makeAPIPostRequest(ENDPOINTS.DATA.FETCH_BLOBS, {
body: uris,
signal,
})
Expand All @@ -114,9 +114,38 @@ function createBlobsRequest(): RequestInstance {
};
}

function createFindDataRequest(isContainer: boolean = true): RequestInstance {
const controller = new AbortController();
const signal = controller.signal;

async function call(queryParams: any): Promise<any> {
return (
await api.makeAPIGetRequest(
isContainer
? ENDPOINTS.DATA.FIND_CONTAINER
: ENDPOINTS.DATA.FIND_SEQUENCE,
{
query_params: queryParams,
signal,
},
)
).body;
}

function cancel(): void {
controller.abort();
}

return {
call,
cancel,
};
}

export {
createFetchDataRequest,
createFetchGroupedSequencesRequest,
createRunFunctionRequest,
createBlobsRequest,
createFindDataRequest,
};
79 changes: 56 additions & 23 deletions src/aimcore/web/ui/src/pages/Board/Board.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import { Box, Button, Link, Tabs } from 'components/kit_v2';
import { PathEnum } from 'config/enums/routesEnum';

import { search } from 'pages/Board/serverAPI/search';
import { find } from 'pages/Board/serverAPI/find';

import usePyodide from 'services/pyodide/usePyodide';
import pyodideEngine from 'services/pyodide/store';
Expand Down Expand Up @@ -241,36 +242,68 @@ def set_session_state(state_slice):
if (!getQueryResultsCacheMap().has(queryKey)) {
return;
}
const {
boardPath: queryBoardPath,
type_,
query,
count,
start,
stop,
isSequence,
} = getQueryResultsCacheMap().get(queryKey).params;

try {
getQueryResultsCacheMap().delete(queryKey);
search(
queryBoardPath,
if (getQueryResultsCacheMap().get(queryKey).type === 'filter') {
const {
boardPath: queryBoardPath,
type_,
query,
count,
start,
stop,
isSequence,
() => {
queryKeysForCacheCleaningRef.current[queryKey] = true;
},
);
} catch (ex) {
if (ex === 'WAIT_FOR_QUERY_RESULT') {
return;
} = getQueryResultsCacheMap().get(queryKey).params;

try {
getQueryResultsCacheMap().delete(queryKey);
search(
queryBoardPath,
type_,
query,
count,
start,
stop,
isSequence,
() => {
queryKeysForCacheCleaningRef.current[queryKey] = true;
},
);
} catch (ex) {
if (ex === 'WAIT_FOR_QUERY_RESULT') {
return;
}
// eslint-disable-next-line no-console
console.warn(ex);
}
} else {
const {
boardPath: queryBoardPath,
type_,
isSequence,
hash_,
name,
ctx,
} = getQueryResultsCacheMap().get(queryKey).params;

try {
getQueryResultsCacheMap().delete(queryKey);
find(
queryBoardPath,
type_,
isSequence,
hash_,
name,
ctx,
() => {
queryKeysForCacheCleaningRef.current[queryKey] = true;
},
);
} catch (ex) {
if (ex === 'WAIT_FOR_QUERY_RESULT') {
return;
}
// eslint-disable-next-line no-console
console.warn(ex);
}
// eslint-disable-next-line no-console
console.warn(ex);
}
}, liveUpdateInterval);
}
Expand Down
Loading
Loading