-
Notifications
You must be signed in to change notification settings - Fork 71
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
Request streaming with Zinc #1196
Conversation
As we discussed in SeasideSt/Grease#103 I've moved I've also renamed
|
I've reverted the renaming of Zinc-Seaside and opened a separated issue to do it for 3.6: #1197 |
@theseion Some of the changes to the core of the Zinc-Seaside package are breaking things in GemStone. I can take a look if I can 'fix' them but it will probably be only by the end of the week. Another option is create a specific subclass for the adapter and use that one in Pharo? |
Actually, nothing should break, that's why we put everything into a Pharo specific package. I'll look into it, maybe it's just a problem with the baseline. |
I did not investigate into detail, but there are still changes to the Zinc-Seaside package itself. My guess is that these break the Zinc adapter in GS. I did not try, so I cannot tell for sure. |
hey @theseion If not, I can take a look as it's Gemstone tests that are failing. But it would be better to have the last version first merged back into this branch as I have been making extensive changes for Gemstone tests on master. |
8298623
to
c998a30
Compare
@jbrichau I've picked this one up again (it's been a while...). It requires the changes from SeasideSt/Grease#138. |
Set up for quick testing:
|
|
I removed the expected failure from the master branch. Squeak will be left unmaintained if nobody takes care of it. I don't have the time to dedicate to it. |
Some things would need to be cleared up before we can merge this one into master:
I'm willing to help out getting things sorted. If you want, merge it into a branch on SeasideSt and we can work on it collaboratively? That would also help me getting the GemStone implementation merged in (if I can fix it) |
You already have write access to this branch, I don't think I need to move it to SeasideSt. Or do you need it on SeasideSt for Gemstone? I will rebase on top of master and start addressing the things you've listed. I'll start with Thanks for the help! |
146559a
to
f6db3c4
Compare
Fair. @tcj might be able to help with Squeak? |
|
I will help as best I can. Does it help for me to run smalltalkCI locally? (Running it for the first time locally now.) I understand this is about getting the The failure behind
|
Thanks for offering @tcj.
That certainly helps, yes.
Correct. There are a couple of tests that have been failing in Squeak for a while.
That would be a great start, yes! |
repository/Zinc-Seaside.package/ZnZincServerAdaptor.class/instance/responseFrom..st
Outdated
Show resolved
Hide resolved
Thanks for working on this! I'll get back to this as soon as possible. |
@theseion no problem. I just did a bit of integration work and the streaming seems to work fine. I still need to take a look at the gemstone issues that cause the builds to break. |
# Conflicts: # repository/Zinc-Seaside.package/ZnZincServerAdaptor.class/instance/requestHeadersFor..st
I think I'm almost there. The last commits show I need to catch some sleep before finishing this off. |
@theseion Almost there! GemStone 3.7 works: https://github.com/SeasideSt/Seaside/actions/runs/7244577602 |
Wow! Thanks! |
@theseion All tests are green now. Looks good to me. What do you think? |
...tiPartFormDataEntity.class/instance/parseMultiPartFieldWithoutLengthWithBoundary.writeOn..st
Outdated
Show resolved
Hide resolved
...ackage/ZnStreamingMultiPartFormDataEntity.class/instance/partsDecodeWith.decodeFilesWith..st
Outdated
Show resolved
Hide resolved
...ackage/ZnStreamingMultiPartFormDataEntity.class/instance/partsDecodeWith.decodeFilesWith..st
Outdated
Show resolved
Hide resolved
...ackage/ZnStreamingMultiPartFormDataEntity.class/instance/partsDecodeWith.decodeFilesWith..st
Outdated
Show resolved
Hide resolved
...ackage/ZnStreamingMultiPartFormDataEntity.class/instance/partsDecodeWith.decodeFilesWith..st
Outdated
Show resolved
Hide resolved
...ackage/ZnStreamingMultiPartFormDataEntity.class/instance/partsDecodeWith.decodeFilesWith..st
Show resolved
Hide resolved
...side-Zinc-Core.package/ZnZincServerAdaptor.class/instance/configureServerForBinaryReading.st
Outdated
Show resolved
Hide resolved
...Seaside-Zinc-Core.package/ZnZincServerAdaptor.class/instance/convertMultipartEntity.with..st
Outdated
Show resolved
Hide resolved
...inc-Core.package/ZnZincServerAdaptor.class/instance/convertMultipartStreamingEntity.with..st
Outdated
Show resolved
Hide resolved
repository/Seaside-Zinc-Core.package/ZnZincServerAdaptor.class/instance/requestAddressFor..st
Outdated
Show resolved
Hide resolved
LGTM. I'm the author of the PR, so I can't review. |
Yay! 🎉 |
…s (revert changes made in #1196)
@theseion I noticed that the Zinc adaptor was doing streaming file uploads when the option was set to false. This was due to boolean mistake that was fixed in 6003bc7. However, I then got the failing test Oh, and Happy New Year! ;-) |
I don't recall the reason for doing it. As far as I recall, it is possible for a file input to be submitted with a file but with an empty file name. In that case, the part should be decoded as a file anyway, which is why I added the Looking at the code again now I think we could just make the following change: "..."
part fileName
ifNil: [ self codec url decode: part fieldValueString ]
ifNotNil: [ self convertMultipartFileField: part ] ].
"..." There's another issue with this code though, as it's now possible to send an unlimited amount of data with |
Addressed the above in cb9f147 |
No, I haven't. I agree, this should probably be part of Zinc. Currently, the implementation relies on features of Seaside (like temporary files), but that shouldn't be a huge issue. I will not have the time to contribute it myself, but I'd be around to advise, of course. |
This PR adds request streaming with Zinc to Seaside.
The use case for this are primarily
multipart/form-data
file uploads. Usually, a request is read into memory completely before being processed, which means the contents of an entire file will end up in memory, regardless of the size of the file. This may kill the image in the worst case or lead to swapping / thrashing on the host machine. With request streaming it is possible to read the request in chunks and write these chunks to disk, so that no more than the chunk size has ever have to be allocated to process the entire file.How it works
I've extended Zinc-Seaside with an option
ZnServer>>streamUploads:
to enable the feature. When request streaming is enabled,multipart/form-data
requests will be read in chunks. If the request contains files they will be streamed to temporary files on disk.There are two new important classes in Zinc-Seaside:
ZnRingBuffer
andZnStreamingMultiPartFormDataEntity
. These are the classes that implement the parsing logic.The temporary files are represented by
WAExternalFile
which I moved to Seaside-Core. Since we already haveWAFile
I've created a hierarchy for file classes to make the different implementations polymorphic as far as possible.I've also extended Grease with two methods for creating and writing temporary files (see SeasideSt/Grease#103).
Caveats
This should all be part of Zinc in my opinion but Zinc has a lot of changes that aren't yet part of the stable image. Those changes will make some of the things simpler but they also make some things harder, e.g. it will no longer be possible to use
ZnRingBuffer
because the underlying buffered streams will pass the buffer to primitives (can't work sinceZnRingBuffer
is a wrapper`).I'm hoping that we can contribute this to Zinc in the future but for now I think it's best to have all the code in one place.
Additional stuff
This PR also includes overrides of Zinc methods that don't respect custom encoding (uses
ZnCharacterEncoder utf8
instead ofZnCharacterEncoder default
, which falls back to usingZnDefaultCharacterEncoder value
, which in turn can be set with#defaultEncoder: on
ZnServer`).