Refactor graphImageResponse to use Temporary Files#1667
Refactor graphImageResponse to use Temporary Files#1667a1-su wants to merge 3 commits intoCourseography:masterfrom
Conversation
Pull Request Test Coverage Report for Build b17a4f5a-53dd-4f11-807c-7a64c9ccb0cbDetails
💛 - Coveralls |
| graphInfo <- look "JsonLocalStorageObj" | ||
| (svgFilename, imageFilename) <- liftIO $ getActiveGraphImage graphInfo | ||
| liftIO $ returnImageData svgFilename imageFilename | ||
| liftIO $ withSystemTempFile "graph.svg" $ \svgPath svgHandle -> do |
There was a problem hiding this comment.
the filenames should still be random (want to avoid possible name collisions if multiple responses are being executed at the same time)
There was a problem hiding this comment.
I could be mistaken, but the withSystemTempFile accounts for this automatically. The "graph.svg" and "graph.png" are file name templates, which have a random number placed after the file name but before the file extension when created, so name collisions are avoided and a random number doesn't need to be added manually.

There was a problem hiding this comment.
Ah yes that's great, thanks for sharing this element of the documentation. 👍
app/Controllers/Graph.hs
Outdated
| (svgFilename, imageFilename) <- liftIO $ getActiveGraphImage graphInfo | ||
| liftIO $ returnImageData svgFilename imageFilename | ||
| liftIO $ withSystemTempFile "graph.svg" $ \svgPath svgHandle -> do | ||
| hClose svgHandle |
There was a problem hiding this comment.
You should be able to use this handle, passing it down all the way to buildSVGHelper in order to write directly to the file. This is different from the png temp file, since for the latter the file is being created externally to Courseography (by running magick in a subprocess)
There was a problem hiding this comment.
Unfortunately because of how the helper functions were implemented, the way I've decided to make this change included an hClose inside the getGraphImage function in Export/GetImages.hs, which I'm not sure is ideal if it's being called within a helper function inside a withSystemTempFile (or withFile, which was added because the helper functions are coupled with exportTimetablePDFResponse in Controllers/Timetable.hs).
I wasn't sure if I should have since it was outside the scope of the ticket, but if you'd have preferred, I can move createImageFile, which was previously called in getGraphImage, to be imported in Controllers/Graph.hs instead. This way, hClose can be called inside the withSystemTempFile instead of in a helper function inside withSystemTempFile. To keep the original functionality, this would mean the createImageFile would also need to be called in and duplicated in getActiveGraphImage (inside the withFile) instead of just in one place (because of the coupling with the timetable PDF export). I also chose not to do this since getTimetableImage, a very similar function, uses createImageFile as well and I was worried it would be unintuitive to have them behave differently.
If the timetable export also gets refactored, I can modify the code so it's more cohesive and better follows standard practices, and feel free to let me know if this should be changed.
david-yz-liu
left a comment
There was a problem hiding this comment.
Hi @a1-su, nice work. Overall this is a bit messy because of the issues you've identified with the existing timetable export. Please go ahead and refactor the timetable exporting functions to use the same approach as well. You're definitely on the right track with this and refactoring both will let you clean the up code, so I'm happy for you to proceed with this.
| graphInfo <- look "JsonLocalStorageObj" | ||
| (svgFilename, imageFilename) <- liftIO $ getActiveGraphImage graphInfo | ||
| liftIO $ returnImageData svgFilename imageFilename | ||
| liftIO $ withSystemTempFile "graph.svg" $ \svgPath svgHandle -> do |
There was a problem hiding this comment.
Ah yes that's great, thanks for sharing this element of the documentation. 👍
Proposed Changes
This PR refactors the
graphImageResponsefunction inControllers/Graph.hsto usewithSystemTempFiletemporary files (from thetemporarylibrary in Haskell). Previously the files were being manually generated and deleted, so if an error ever occurred during process of saving the graph, the files would be left undeleted.Note that this modified some other functions, including
getActiveGraphImageinExport/GetImages.hs, which was coupled with theexportTimetablePDFfunction inControllers/Timetable.hs. I've modifiedgetActiveGraphImageto keep its original functionality andgraphImageResponseto use helper functionwriteActiveGraphImage, but shouldexportTimetablePDFever get refactored to also use temporary files andwriteActiveGraphImage,getActiveGraphImagecan be safely removed.Type of Change
(Write an
Xor a brief description next to the type or types that best describe your changes.)Checklist
(Complete each of the following items for your pull request. Indicate that you have completed an item by changing the
[ ]into a[x]in the raw text, or by clicking on the checkbox in the rendered description on GitHub.)Before opening your pull request:
After opening your pull request:
Questions and Comments
(Include any questions or comments you have regarding your changes.)