Skip to content

[full-ci] Enable streaming for propfind#38583

Merged
AlexAndBear merged 1 commit intomasterfrom
feature/sabre-with-streaming-propfind-reloaded
Oct 13, 2021
Merged

[full-ci] Enable streaming for propfind#38583
AlexAndBear merged 1 commit intomasterfrom
feature/sabre-with-streaming-propfind-reloaded

Conversation

@DeepDiver1975
Copy link
Copy Markdown
Member

@DeepDiver1975 DeepDiver1975 commented Mar 25, 2021

Description

Propfind requests will now be streamed to reduce memory usage with large responses.
Additionally, the new config dav.propfind.depth_infinity has been added to tell clients whether depth=infinity is allowed for propfind requests. It defaults to true.

#36336 reloaded
Fixes #14531

Types of changes

  • Bug fix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • Database schema changes (next release will require increase of minor version instead of patch)
  • Breaking change (fix or feature that would cause existing functionality to change)
  • Technical debt
  • Tests only (no source changes)

Checklist:

Copy link
Copy Markdown

@michaelstingl michaelstingl left a comment

Choose a reason for hiding this comment

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

Please add capability for the clients, so they don't meltdown servers without this improvement.

@michaelstingl
Copy link
Copy Markdown

michaelstingl commented Aug 2, 2021

@DeepDiver1975 @hodyroff what's next? Can be released in next iOS version, but there's no capability yet. When can this be released?

@DeepDiver1975
Copy link
Copy Markdown
Member Author

DeepDiver1975 commented Aug 2, 2021

When can this be released?

Once these things are taken care of:

  • capability
  • add dedicated acceptance tests for depth infinity (especially exceptional scenarios)
  • fix any issues which arise (basically fix all acceptance tests when streaming is enabled on all requests/responses)
  • enable streaming only if depth: infinity is used (risk minimization)

total effort: ~2 weeks

@JammingBen JammingBen force-pushed the feature/sabre-with-streaming-propfind-reloaded branch from 5681f1a to 8e4c4a0 Compare October 6, 2021 09:12
@JammingBen JammingBen changed the title Enable streaming for propfind [full-ci] Enable streaming for propfind Oct 6, 2021
@ownclouders
Copy link
Copy Markdown
Contributor

💥 Acceptance tests pipeline apiProxySmoke-8-5-mariadb10.2-php7.4 failed. The build has been cancelled.

https://drone.owncloud.com/owncloud/core/32901/172/1

@JammingBen
Copy link
Copy Markdown
Contributor

@DeepDiver1975

Regarding those invalid XML responses:

<?xml version="1.0" encoding="utf-8"?>
<d:error xmlns:d="DAV:" xmlns:s="http://sabredav.org/ns">
  <s:exception>Sabre\DAV\Exception\NotFound</s:exception>
  <s:message>Principal with name dff not found</s:message>
</d:error>
<?xml version="1.0"?>
<d:multistatus xmlns:d="DAV:" xmlns:s="http://sabredav.org/ns" xmlns:oc="http://owncloud.org/ns"% 

I think the problem exists in the DAV lib: https://github.com/sabre-io/dav/blob/master/lib/DAV/Server.php#L1640. $w->openUri('php://output'); will be called, then $this->writeMultiStatus($w, $fileProperties, $strip404s);. This is the place where exceptions will be thrown in case of an invalid request. Because exceptions are not catched here, $w->flush(); will never be called -> the stream doesn't end properly -> bad.

With something like this it works for me:

try {
    $this->writeMultiStatus($w, $fileProperties, $strip404s);
} catch (\Exception $e) {
    $w->flush();
    throw $e;
}

2 things I'm currently not sure of:

  • Why are our errors thrown in writeMultiStatus()? Is this the "normal"/recommended way?
  • Can we hook into this call somehow to fix it? Doesn't look like so to me...

@DeepDiver1975
Copy link
Copy Markdown
Member Author

My expectation would be that writeMultiStatus never throws an exceptions.

This is what I was mentioning earlier: we need to make sure that either all conditions which could throw an exception are caught earlier.
Or that in case of an exception within writeMultiStatus we catch it locally and write the corresponding status within the multi status

@AlexAndBear AlexAndBear force-pushed the feature/sabre-with-streaming-propfind-reloaded branch from a15a344 to c49dc1c Compare October 7, 2021 10:59
@AlexAndBear AlexAndBear force-pushed the feature/sabre-with-streaming-propfind-reloaded branch from f149d0b to d49e3c3 Compare October 7, 2021 11:48
@JammingBen JammingBen force-pushed the feature/sabre-with-streaming-propfind-reloaded branch 4 times, most recently from c8f8cef to 9932411 Compare October 7, 2021 12:51
@JammingBen
Copy link
Copy Markdown
Contributor

JammingBen commented Oct 7, 2021

@DeepDiver1975 Pipeline runs now, please have a look. We basically just added a preflight check if the tree is traversable and if the resource has read permissions in case of a share.

Regarding the open to-dos, please verify the following assumptions:

  • capability -> we just add depth_infinity to the capabilities and set it to true
  • enable streaming only if depth: infinity is used (risk minimization) -> That's outdated, we always enable streaming
  • Unit tests need to be added
  • Acceptance tests need to be added (maybe @phil-davis and his team can support us here)

@JammingBen JammingBen added 2 - Developing app:dav php Pull requests that update Php code labels Oct 7, 2021
@DeepDiver1975
Copy link
Copy Markdown
Member Author

* `capability` -> we just add `depth_infinity` to the capabilities and set it to `true`

please double check if this shall be configurable @michaelstingl @pmaier1

* `enable streaming only if depth: infinity is used (risk minimization)` -> That's outdated, we always enable streaming

👍

* Unit tests need to be added

👍

* Acceptance tests need to be added (maybe @phil-davis and his team can support us here)

👍

@pmaier1
Copy link
Copy Markdown
Contributor

pmaier1 commented Oct 7, 2021

please double check if this shall be configurable @michaelstingl @pmaier1

Please make it configurable, default on. So that we have an easy way to disable it if we encounter issues.

@JammingBen JammingBen force-pushed the feature/sabre-with-streaming-propfind-reloaded branch from 0d9d5be to 9932411 Compare October 8, 2021 07:20
@AlexAndBear
Copy link
Copy Markdown

@pmaier1 @DeepDiver1975 what should happen if depth_infinity is set to false and the client does a propfind with this header, should we throw an error?

@pmaier1
Copy link
Copy Markdown
Contributor

pmaier1 commented Oct 8, 2021

@pmaier1 @DeepDiver1975 what should happen if depth_infinity is set to false and the client does a propfind with this header, should we throw an error?

How do we handle it today?

@JammingBen
Copy link
Copy Markdown
Contributor

PROPFIND with depth=infinity fails if dav.propfind.depth_infinity is set to false
PROPFIND with depth=infinity succeeds if dav.propfind.depth_infinity is set to true (which is default)

I adjusted an existing acceptance test to match these scenarios.

Is there an acceptance test for propfind on a folder which has external storages inside which are (temporarily) not available?

I couldn't find it, but maybe @phil-davis knows.

@JammingBen JammingBen requested a review from phil-davis October 11, 2021 12:57
@JammingBen JammingBen marked this pull request as ready for review October 11, 2021 12:57
Copy link
Copy Markdown
Contributor

@IljaN IljaN left a comment

Choose a reason for hiding this comment

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

Just some optional remarks/thought. LGTM 👍

@phil-davis
Copy link
Copy Markdown
Contributor

Is there an acceptance test for propfind on a folder which has external storages inside which are (temporarily) not available?

Nothing that I am aware of. I don't remember ever coding something that would "pull out the external storage backend" during a test scenario.

Copy link
Copy Markdown
Contributor

@phil-davis phil-davis left a comment

Choose a reason for hiding this comment

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

LGTM

@AlexAndBear AlexAndBear requested a review from IljaN October 13, 2021 07:27
@JammingBen
Copy link
Copy Markdown
Contributor

Nothing that I am aware of. I don't remember ever coding something that would "pull out the external storage backend" during a test scenario.

@phil-davis Could you help us implementing such test?

@phil-davis
Copy link
Copy Markdown
Contributor

Could you help us implementing such test?

@JammingBen we can try. Please create an issue and assign me. If we can do it with "local storage" then it might be easy enough (rename the local storage folder, try some API actions, rename the folder back again, try the API again)

@AlexAndBear AlexAndBear force-pushed the feature/sabre-with-streaming-propfind-reloaded branch from 8233bf3 to daa44f4 Compare October 13, 2021 08:31
@AlexAndBear AlexAndBear force-pushed the feature/sabre-with-streaming-propfind-reloaded branch from daa44f4 to 300d314 Compare October 13, 2021 09:41
@AlexAndBear AlexAndBear force-pushed the feature/sabre-with-streaming-propfind-reloaded branch from 300d314 to 2914ec2 Compare October 13, 2021 12:16
@sonarqubecloud
Copy link
Copy Markdown

Kudos, SonarCloud Quality Gate passed!    Quality Gate passed

Bug A 0 Bugs
Vulnerability A 0 Vulnerabilities
Security Hotspot A 0 Security Hotspots
Code Smell A 1 Code Smell

72.0% 72.0% Coverage
0.0% 0.0% Duplication

@AlexAndBear AlexAndBear merged commit 8b74370 into master Oct 13, 2021
@delete-merged-branch delete-merged-branch bot deleted the feature/sabre-with-streaming-propfind-reloaded branch October 13, 2021 13:07
@jnweiger
Copy link
Copy Markdown
Contributor

jnweiger commented Nov 22, 2021

Capability for recursive propfind confirmed in 10.9.0 beta1:

curl -k -s -u admin:admin 'https://localhost/ocs/v1.php/cloud/capabilities?format=json' | jq .ocs.data.capabilities.dav.propfind
{
  "depth_infinity": true
}

But no capabiltiy seen, that mentions streaming. Probably OK.

@jnweiger
Copy link
Copy Markdown
Contributor

Confirmed fixed in 10.9.0 RC2

  • On a tree with 40000 files and folders, the first output appears conistently within 10 seconds:
  • curl -k -s -u admin:admin -XPROPFIND https://$server/remote.php/dav/files/admin/Deep -H "Depth:infinity" | pv > /dev/null
  • total wall clock time: 43 sec.

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

Labels

app:dav php Pull requests that update Php code

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Depth infinity: Make recursive PROPFIND calls cheaper