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

[WIP] Wait for task no longer #9352

Open
wants to merge 4 commits into
base: master
Choose a base branch
from
Open

Conversation

kbrock
Copy link
Member

@kbrock kbrock commented Feb 19, 2025

Overview

Depends upon

Issue

The wait_for_task mechanism relies upon the session.
Every http request changes the session. So when multiple requests come in, updates to the session can overwrite the changes done by another request.

Example:

Host's display of Cap&U was breaking because hits to notifications were overwriting the session variables. Note: VM's display of Cap&U was working fine because it did not have a hit to notifications (and therefore didn't have this race condition).

Solution

Move wait_for_task parameters from the session to the url.

Before

  • initiate_wait_for_task sets session[:async][:params] with action and params{}
  • browser_refresh_task puts shim into web page
  • browser polls wait_for_task waiting for task to complete
  • when task is complete, session[:async][:params] is used to complete action

After

  • initiate_wait_for_task gathers async_params
  • browser_refresh_task puts shim into web page with async_params
  • browser polls wait_for_task waiting for task to complete.
  • when task is complete, url parameters (async_params) is used to complete action

@kbrock kbrock requested a review from a team as a code owner February 19, 2025 21:58
@kbrock
Copy link
Member Author

kbrock commented Feb 19, 2025

@Fryguy This still stores the parameters in the session to be backwards compatible. Do you want to change 10 other controllers and remove this completely from the session?

Pro: eradicates race condition and completely removes session values
Con: This is an extra to 10 controllers (25 lines)

end

browser_refresh_task(task_id, !!options[:flash])
session[:async][:params] = async_params
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think you need the ||= {} up above to ensure this path exists.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

good eye.
My question below is if we can drop session[:async] all together.
In the meantime, I'll add it back.

session[:async][:interval] ||= 1000 # Default interval to 1 second
session[:async][:params] ||= {}
async_interval = params[:async_interval] || 1000 # Default interval to 1 second
async_params = params[:async_params] || session[:async][:params]
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think I like the async_params coming in as a regular param - not sure why that is needed.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

that is the whole solution.
Otherwise it is a last one in. in our case, it gets blown away by notifications url hit.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

moved over to Task

render :update do |page|
page << javascript_prologue
ajax_call = remote_function(:url => {:action => 'wait_for_task', :task_id => task_id})
page << "setTimeout(\"#{ajax_call}\", #{session[:async][:interval]});"
ajax_call = remote_function(:url => {:action => 'wait_for_task', :task_id => task_id, :async_params => async_params, :async_interval => :async_interval})
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh because of this ... hmmmm

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

async_parameters have been removed. now it only contains async_interval

@kbrock
Copy link
Member Author

kbrock commented Feb 19, 2025

ok, so we have a security problem just passing the action. The send(param[:action]) is pretty wide open. Even if we change to a public_send.


The action typically comes from params[:action] which is the url but those are protected.
In other cases, the action is from the url, which keeps getting hit until the task_id is completed.

This new way passes action as a param (user editible) and that is not protected like it is when it comes in via the url.

I can probably change these urls to have a single url with a blocker on a completed task_id (vs having a #{action}_finished pattern.

Aside: Also, these all use rjs. Would have been nice to drop that as well, but this is starting to get serious scope creep.

@kbrock kbrock changed the title Wait for task no longer [WIP] Wait for task no longer Feb 20, 2025
@kbrock
Copy link
Member Author

kbrock commented Feb 20, 2025

WIP: moving parameters into the Task.

It is unfortunate that the task is created elsewhere - so we need to find and then update it

@kbrock
Copy link
Member Author

kbrock commented Feb 21, 2025

update:

  • moved async_params to MiqTask

WIP: This PR is complete. First commit is from #9358 - after merging, can up-WIP

We were storing in session[:async][:params], but that ended up with a race condition
and didn't allow multiple tabs
@kbrock
Copy link
Member Author

kbrock commented Feb 21, 2025

update:

  • fixed stub in spec to properly return a task_id

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants