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

server: Skip redundant maxPrice check in ongoing session #2994

Merged
merged 5 commits into from
Apr 3, 2024

Conversation

victorges
Copy link
Member

@victorges victorges commented Apr 2, 2024

What does this pull request do? Explain your changes. (required)
After #2981, we started allowing both Bs and Os to updated their prices dynamically over time
based on an external currency. This creates a problem for Bs, given their maxPrice could
become lower than an Os price in the middle of a session. Even though we want the price to
be dynamic, we want a given session prices to be negotiated in the beginning of the session,
and don't want to drop a session mid-transcoding because the prices were updated.

The initial intuition was to save the "initial max price" on the BroadcastSession object as well,
but we realized that this logic would be redundant given we already check for the max price when
the session is estabilished in the first place, and disallow the O to increase prices mid-session.
It goes something like this:

  • On session start, we already check O price <= B maxPrice
  • We save the O price as initialPrice, and would save B price as initialMaxPrice
    • Thus we have that O initialPrice <= B initialMaxPrice
  • During session, we also already check that O price <= O initialPrice (kept this check on the same validatePrice func)
  • So this means O price <= O initialPrice <= B initialMaxPrice
  • i.e. necessarily O price <= B initialMaxPrice, which means we don't need a separate check for that (nor even saving the initialMaxPrice, as that would be its only use)

Specific updates (required)

  • Remove maxPrice check from validatePrice
  • Fix tests

How did you test each of these updates (required)
Ran automated tests.

Does this pull request close any open issues?
Related to ENG-1855 but a bit parallel to that

Checklist:

When I was writing the tests for validatePrice I found out
we were using that function wrong in a couple places and
never checking any error. We were sending err.Error() to check
the error from err.
Copy link

linear bot commented Apr 2, 2024

@victorges victorges requested a review from leszko April 2, 2024 15:19
Copy link

codecov bot commented Apr 2, 2024

Codecov Report

All modified and coverable lines are covered by tests ✅

Project coverage is 57.44328%. Comparing base (85bea86) to head (73fd824).

Additional details and impacted files

Impacted file tree graph

@@                 Coverage Diff                 @@
##              master       #2994         +/-   ##
===================================================
- Coverage   57.47690%   57.44328%   -0.03362%     
===================================================
  Files             92          92                 
  Lines          15695       15692          -3     
===================================================
- Hits            9021        9014          -7     
- Misses          6078        6080          +2     
- Partials         596         598          +2     
Files Coverage Δ
server/segment_rpc.go 79.10156% <ø> (-0.12174%) ⬇️

... and 1 file with indirect coverage changes


Continue to review full report in Codecov by Sentry.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update 85bea86...73fd824. Read the comment docs.

Files Coverage Δ
server/segment_rpc.go 79.10156% <ø> (-0.12174%) ⬇️

... and 1 file with indirect coverage changes

@eliteprox
Copy link
Contributor

For this change, I validated the discovery loop still selects orchestrator via price. In testing this change allowed an orchestrator that is specified by the broadcaster with -orchAddr to have a higher price than the max price on the broadcaster. However, I think this might be okay.

Do we really need the validatePrice() function? We can use sess.InitalPrice instead of getting a fresh price from the orchestrator during every segment. This would eliminate both checks done by validatePrice(). See commit 9866e77

If we need to keep price validation, perhaps it can be moved to when the session is created?

@victorges
Copy link
Member Author

Hey @eliteprox, thank you for reviewing and testing this further! I agree that it should be fine to allow overriding the price for an O to sth higher than the max, given it's an explicit override.

Also had seen your PR and thought that the validatePrice function could completely disappear if we did both. Unfortunately, I don't have enough context yet on the SubmitSegment function to know if the B could just start sending a different price than what the O is currently configured with. I'm currently digging through that code.

I believe the spirit of the original fix though (#2892), was to make the prices sticky for a given session on the O side, so they would never return a different price for a given session. While we have updated the PriceInfo function on that PR to return a fixed number, I think there may be other flows where it should be updated (like the handler of SubmitSegment itself) which could break if the B started sending a different price (from current O config). So I'm currently trying to understand that whole flow to evaluate what's the proper fix.

In the meantime, a solution we are evaluating is to allow some price change on the O until we figure out what is making the price to get updated for a running O session. My current suspicion is this, which updates the sess.OrchestratorInfo based on the response from a SubmitSegment, but will need to dig&test further.

Then for the fix, we could merge this PR (#2994), and temporarily merge #2995 until we make the prices actually stick during a session. There will be a risk of dropping sessions until we do that, but it'd be much lower given the 2x increase threshold. Then we can go on with the migration to USD prices in the meantime.

Let me know if you have any thoughts!

@eliteprox
Copy link
Contributor

Also had seen your PR and thought that the validatePrice function could completely disappear if we did both. Unfortunately, I don't have enough context yet on the SubmitSegment function to know if the B could just start sending a different price than what the O is currently configured with. I'm currently digging through that code.

The broadcaster seems to be refreshing the pricing info on every segment when generating tickets. I think it will be safer and simpler to use sess.InitialPrice from the session instead

if err := validatePrice(sess); err != nil {
return "", err
}
protoPayment := &net.Payment{
Sender: sess.Broadcaster.Address().Bytes(),
ExpectedPrice: sess.OrchestratorInfo.PriceInfo,
}

If we use sess.InitialPrice like in #2991, the broadcaster should pay tickets only on the initially agreed price, unless the session resets and comes back to the same O, then it would continue at the new price.

In the meantime, a solution we are evaluating is to allow some price change on the O until we figure out what is making the price to get updated for a running O session. My current suspicion is this, which updates the sess.OrchestratorInfo based on the response from a SubmitSegment, but will need to dig&test further.

As for removing the maximum price check here, I'm also in support of that because it is already validated when the session begins. If the price should remain the same for the entire session, it makes sense to not update or validate it on each segment. I much prefer this approach over #2995 and I think it is more secure/reliable overall.

I opened #2996 to track the issue since we have a few solutions out there.

@victorges
Copy link
Member Author

@eliteprox thanks for the further input. Unfortunately it shouldn't be so simple as sending a different price on the B side, since the problem is exactly that the O is updating the current price for the session while it is running. On that case, it will naturally reject segments whose price doesn't match its internal state (otherwise the B could just choose to pay "zero" for every segment). So the correct fix here, given we want to have fixed prices for a running session, is to correct the O logic that is losing the current price for the session.

As for removing the maximum price check here, I'm also in support of that because it is already validated when the session begins. If the price should remain the same for the entire session, it makes sense to not update or validate it on each segment. I much prefer this approach over #2995 and I think it is more secure/reliable overall.

FTR the maxPrice change (this PR) is independent of the O price-change validation done in #2995. This PR is required regardless of how we fix the O price-change validation, with the objective of being resilient to maxPrice updates given they're also gonna be set in USD.

As for the other issue, we cannot remove the price-change validation altogether otherwise Os could increase their price indefinitely in the middle of a session (B risk), while we also can't just set any price on the B otherwise the Os that would be at risk (since they'd need to stop validating the segment prices, as explained above).

So, the ideal solution is to fix the O behavior not to lose the fixed price in the middle of a session. We are carrying on the investigation about that (all help appreciated!), but in the meantime we're deploying this and #2995 to allow the prices to change based on USD quote (up to 2x since the session started, for O prices). This will stop dropping most of the sessions (ETH price would need to drop 2x in 1h) until we figure out why the prices are changing mid-session.

@victorges victorges merged commit 07fed97 into master Apr 3, 2024
18 checks passed
@victorges victorges deleted the vg/fix/max-price-check branch April 3, 2024 11:44
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

3 participants