-
Notifications
You must be signed in to change notification settings - Fork 4
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
Attempt to fix Result block don't get updated properly #432 #435
base: main
Are you sure you want to change the base?
Conversation
@@ -21,6 +21,8 @@ generate_server.result_field <- function(x, ...) { | |||
res <- get_stack_result( | |||
get_workspace_stack(inp) | |||
) | |||
# Handle the join block |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The join block was broken since we do this:
by_choices <- function(data, y) {
intersect(colnames(data), colnames(y))
}
and y
is a reactive expression coming from the result field, which means it needs to be evaluated to get the correct result. I believe the best place to do this is here, in the server logic rather than in the code block code.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This shouldn't cause problems: y
from "within the block" should not behave as reactive, but as regular R value. All of this should happen in value()
:
Lines 184 to 209 in 061ac78
value.result_field <- function(x, name = "value") { | |
stopifnot(identical(name, "value")) | |
field <- get_field_value(x, "value") | |
if (length(field) && field %in% list_workspace_stacks()) { | |
res <- get_stack_result(get_workspace_stack(field)) | |
if (inherits(res, "reactive")) { | |
if (is.null(getDefaultReactiveDomain())) { | |
list() | |
} else { | |
res() | |
} | |
} else { | |
res | |
} | |
} else { | |
list() | |
} | |
} |
So if this is still an open issue (is it?), the question is why the "reactive representation" slips through here.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sorry. missed this part of the code. Debugging with a new_join_block
shows we never enter the first if statement as list_workspace_stacks()
always return character(0).
To reproduce:
serve_workspace(
stack1 = new_stack(
blockr.pharmaverseadam::new_adam_block("adae")
),
stack2 = new_stack(blockr.pharmaverseadam::new_adam_block("adsl"), new_join_block(y = "stack1"))
)
@@ -702,9 +714,17 @@ generate_server.workspace <- function(x, id, ...) { | |||
}) | |||
|
|||
attr(x, "reactive_stack_directory") <- reactive({ | |||
names(vals$stacks) | |||
vals$stacks |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We need to pass the stacks to do further check within the result field server logic.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just for my understanding: why do we need to pass through the entire stacks here? Initially the intention for the reactive_stack_directory
was just to give a reactive object for populating result field drop-downs. Where do we need the reactive stack? Sorry, I didn't spot anything relevant in your changes.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I see, it is the validity check for the dependent stack that this is used for. If this is the chase, the result field validator should take care of this, no? Can we extend
Lines 298 to 312 in 061ac78
validate_field.result_field <- function(x) { | |
field <- get_field_value(x, "value") | |
validate_string(field) | |
if (!field %in% list_workspace_stacks()) { | |
validation_failure( | |
"result fields have to refer to existing stack names", | |
class = "result_failure" | |
) | |
} | |
NextMethod() | |
} |
to not only check for existence of a stack, but also it's "validity"?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I played around this idea in 5822c89. However, while it works well for a "static" case, that is, with predefined stacks, it fails in the dynamic case when block are added on the fly:
# works
serve_workspace(
stack1 = new_stack(new_dataset_block("BOD"), new_select_block()),
stack2 = new_stack(new_result_block("stack1"))
)
# fails: to replicate, add a new_select_block on the fly and nothing happens.
serve_workspace(
stack1 = new_stack(new_dataset_block("BOD")),
stack2 = new_stack(new_result_block("stack1"))
)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actually this just does not work. My workspace was already contaminated by other existing stacks so I though it worked but no ...
chr_ply(lapply(vals$stacks, `[[`, "stack"), attr, "title") | ||
c( | ||
chr_ply(lapply(vals$stacks, `[[`, "stack"), attr, "title"), | ||
lapply(vals$stack, \(stack) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
added an extra trigger each time a block changes and it's validity change, otherwise the result field does not update consistently.
), | ||
{ | ||
lapply(vals$blocks, \(block) { | ||
req(block) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
a little extra check to prevent this event from triggering when vals$block is a list of NULL elements.
@@ -44,13 +44,18 @@ generate_server.result_field <- function(x, ...) { | |||
updateSelectInput( | |||
session, | |||
"select-stack", | |||
choices = result_field_stack_opts(session$ns, workspace_stacks()), | |||
choices = result_field_stack_opts(session$ns, names(workspace_stacks())), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Since we pass the entire stack object in the reactive_stack_directory
, we just extract the names to display them in the select choices.
@@ -50,6 +50,7 @@ generate_server.result_field <- function(x, ...) { | |||
) | |||
|
|||
reactive({ | |||
req(input[["select-stack"]]) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is needed now as this expression takes dependencies on other reactive element. Avoids to subset when input$select-stack is NULL.
@@ -210,7 +219,7 @@ generate_server_block <- function( | |||
out_dat <- if (attr(x, "submit") > -1) { | |||
eventReactive(input$submit, | |||
{ | |||
req(is_valid$block) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
req was blocking the reactive chain. We just return an empty data.frame if invalid.
R/server.R
Outdated
if (is.null(in_dat()) && !inherits(x, "transform_block")) { | ||
evaluate_block(blk()) | ||
} else { | ||
if (nrow(in_dat()) == 0 && !inherits(x, "parser_block")) return(data.frame()) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
parser_block
are an exception as their input isn't rectangular data but a file path.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I actually replaced this by:
if (inherits(in_dat(), "data.frame") && nrow(in_dat()) == 0) {
return(data.frame())
}
as it broke the plots.
all_valid <- lgl_ply(blocks, \(block) { | ||
block$is_valid() | ||
}) | ||
if (all(all_valid) == TRUE) get_result(input[["select-stack"]]) else data.frame() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Overall, we check that the previous stack is valid (otherwise the result block has no way to know about the previous blocks from the linked stack). Note: this will be superseded in the stack validation PR #427.
R/server.R
Outdated
@@ -236,7 +236,9 @@ generate_server_block <- function( | |||
if (is.null(in_dat()) && !inherits(x, "transform_block")) { | |||
evaluate_block(blk()) | |||
} else { | |||
if (nrow(in_dat()) == 0 && !inherits(x, "parser_block")) return(data.frame()) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
sorry this thing was a dumb idea from me ...
@nbenn. I believe this PR fixes the result block update issues, as well as the join block problem. I left comments next to each change to give further context.
I tested this PR with this codes:
Again, for the long term, I still have concerns with passing reactive expressions between modules within attributes as it may be very confusing for someone to read and debug the code. That said, in the sort term, as the workshop is coming very soon, we can go ahead with this and try to rework/improve it in the #427 stack validation PR. Happy to chat about it.