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

tec: Refactor the export feature #3045

Merged
merged 1 commit into from
Jun 13, 2020

Conversation

marienfressinaud
Copy link
Member

Closes #3035

Changes proposed in this pull request:

Even if the issue #3035 seemed pretty simple at a first glance, it was
more complicated than I expected. Because we send CSP headers AFTER
running the controller actions, it means we can't "echo" any content
from the controller. It's in fact a good practice, but it was easier at
the time we developed the feature.

To fix that, the only thing I had to do was to move the print() and
readfile() function into the view. The problem was that we needed to
output the content from the CLI too. Then, things became more
complicated. I decided to extract the export-related methods in a
FreshRSS_Export_Service class, in order to use it from both the
controller and the CLI. It was an opportunity to refactor the whole
feature in order to make it a bit more linear and easy to read.

How to test the feature manually:

  1. Export OPML, labelled, starred, and feeds files (one by one, then several to generate a Zip) from the browser
  2. Run the php cli/export-zip-for-user.php and php cli/export-opml-for-user.php commands
  3. Verify none of the files contain an error and that they can be imported back to FRSS

Pull request checklist:

  • clear commit messages
  • code manually tested
  • N/A unit tests written (optional if too hard)
  • N/A documentation updated

Additional information can be found in the documentation.

Even if the issue FreshRSS#3035 seemed pretty simple at a first glance, it was
more complicated than I expected. Because we send CSP headers AFTER
running the controller actions, it means we can't "echo" any content
from the controller. It's in fact a good practice, but it was easier at
the time we developed the feature.

To fix that, the only thing I had to do was to move the `print()` and
`readfile()` function into the view. The problem was that we needed to
output the content from the CLI too. Then, things became more
complicated. I decided to extract the export-related methods in a
`FreshRSS_Export_Service` class, in order to use it from both the
controller and the CLI. It was an opportunity to refactor the whole
feature in order to make it a bit more linear and easy to read.

Reference: FreshRSS#3035
@@ -720,76 +720,6 @@ private function addFeedJson($origin) {
return $return;
Copy link
Member Author

Choose a reason for hiding this comment

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

The diff concerning this file is a bit complicated to review, I suggest to only read the new file

return [
"feeds_{$day}.opml.xml",
$view->helperToString('export/opml')
];
Copy link
Member Author

Choose a reason for hiding this comment

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

I'm not completely happy with this pattern (i.e. returning an array containing the filename and the content) but it makes the things easier in the controller and the cli

$type, '', FreshRSS_Entry::STATE_ALL, 'ASC', -1
);
$view->entryIdsTagNames = $this->tag_dao->getEntryIdsTagNames($view->entriesId);
// The following is a streamable query, i.e. must be last
Copy link
Member Author

Choose a reason for hiding this comment

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

I kept this comment line, but I didn't understand its meaning

Copy link
Member

Choose a reason for hiding this comment

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

It could be reworded :-P
We cannot have two streamed SQL requests on the same DB connection at the same time

Copy link
Member Author

Choose a reason for hiding this comment

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

No it's fine, it's just that I wasn't able to spot the difference between this method and the others. But I just realize that fetchAll() isn't called, and I didn't know that PDOStatement implemented the Traversable interface

@@ -0,0 +1 @@
<?= $this->content ?>
Copy link
Member Author

Choose a reason for hiding this comment

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

This is the real fix of #3035 :)

Minz_Request::param('export_starred', false),
Minz_Request::param('export_labelled', false),
Minz_Request::param('export_feeds', array())
return Minz_Request::forward(
Copy link
Member Author

Choose a reason for hiding this comment

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

I just remembered I forgot to explain these return. It's actually useless because the forward(..., true) will immediately trigger a redirection, but it's implicit and not clear for a new developer. I suggest we start to put explicit return when we want the method to stop, what do you think?

Copy link
Member

Choose a reason for hiding this comment

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

Yes, that sounds good indeed

@Alkarex Alkarex added this to the 1.17.0 milestone Jun 10, 2020
@Alkarex
Copy link
Member

Alkarex commented Jun 13, 2020

Looks good.
Not necessarily for this PR, but:

  • Maybe we should have a default limit for the number of exported articles via the CLI when using the ZIP method (which is currently loading everything in memory and therefore only works for tiny cases):
docker exec --user www-data freshrss cli/export-zip-for-user.php --user alex
FreshRSS exporting ZIP for user “alex”…
PHP Fatal error:  Allowed memory size of 134217728 bytes exhausted (tried to allocate 290816 bytes) in /var/www/FreshRSS/app/Services/ExportService.php on line 175

@marienfressinaud
Copy link
Member Author

Maybe we should have a default limit for the number of exported articles via the CLI when using the ZIP method

Do you mean the $number_entries variable (default is 100) or something else?

@Alkarex
Copy link
Member

Alkarex commented Jun 13, 2020

Yes @marienfressinaud , this is what I mean. I did not check and - due to the memory problem I observed - assumed there was no default limit through the CLI. Now that we have the SQLite export (which uses streams), the ZIP export is less relevant, but I do not like the fact that it uses so much memory and crashes even for light exports. This might be out of scope for this PR though

@Alkarex
Copy link
Member

Alkarex commented Jun 13, 2020

Suggestion for future work:

  • Keep the OPML export as it is;
  • Keep the JSON export of favourites / labels almost as it is, but modify it to stream the output;
  • Promote the SQLite export/import so that is is accessible from the Web interface (in addition of CLI);
  • Remove the ZIP export (but keep the ZIP import for now) as it is a bit redundant and would require more work to re-implement in a memory friendly way.

@Alkarex Alkarex merged commit 15505a0 into FreshRSS:master Jun 13, 2020
@marienfressinaud marienfressinaud deleted the fix/3035/warning-on-opml-export branch June 14, 2020 07:54
@Alkarex Alkarex modified the milestones: 1.17.0, 1.16.3 Aug 29, 2020
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.

OPML export has PHP warning at the bottom: "Cannot modify header information"
2 participants