render_sync
render_sync copied to clipboard
Rough STOMP Adapter
Purpose: Adds STOMP adapter + interfaces + documentation for use with Sync.
Changes:
- [X] Exercise more built-in bundler functionality in
.travis.yml
and force install. - [X] Added / Updated ruby versions in
.travis.yml
- [X] Add
rabbitmq
service and configuration in.travis.yml
(for STOMP) - [X] Add
api_key
,auth_token
,websocket
,destination
, anddebug
to configuration. - [X] Allow
debug
to fall back as true for!production?
when omitted fromsync.yml
. - [X] Allow
Sync.onReady(..)
to accept an array of callbacks. - [X] Ensure
Sync.readyQueue
callbacks do not fire until adapter is available and connected.- [X] Start Sync inside self-closing interval (in case adapter dependency loading is deferred).
- [X] Defer
Sync.onReady
callbacks until adapter is connected (seeonConnectInterval
).
- [X] Use
api_key
andauth_token
forlogin
andpasscode
for STOMP client authentication. - [X] Removed redundant
subscribe(..)
under Pusher adapter class. - [X] Rename
PUSHER_API_KEY
to simplyAPI_KEY
. - [X] Added
Stomp
adapter + subscription classes tosync.coffee.erb
. - [X] Added
Stomp
client adapter in ruby. - [X] Added template specification for STOMP adapter to
sync.yml
. - [X] Added message test, test helper, and fixture for STOMP.
- [x] Updated
README.md
with basic instructions for using the STOMP adapter with RabbitMQ. - [X] Force
bundler
gem update in.travis.yml
.- Fix for issue bundler/bundler#3558.
@chrismccord Thoughts?
It would be nice if this could be done as an external adapter. Any thoughts on going that approach?
Hey, @chrismccord.
It shouldn't be too hard to extract it to it's own gem. I was actually going to suggest that we extract Faye, Pusher, and this adapter out to their own plugin projects after this iteration was complete.
I think, though, that we need to solidify and maybe refactor a couple of the interface patterns used throughout the gem before we go down that route. Here are some thoughts:
-
Sync::Clients
: We should define a base interface that other client adapters inherit from, which throws NotImplementedError's when necessary to emphasize expected delegation to the child class. Doing so would establish a very clear set of expectations and directions for the development of other adapters. It would probably yield more reusable patterns for testing examples, too. -
Sync.Adapter
: The idea is generally the same as above, but as this structure is much more evolved than on the ruby side, I think maybe only a little bit of cleaning would be necessary here. Probably just a more strict set of expectations or documentation regarding callbacks and boot structure, and it'd be done. -
Extract inline-rendered javascript snippets from the ruby files into templates.
-
The general file organization under
lib/sync
could do with some cleaning, and could probably make good use ofActiveSupport::Concern
versus vanilla module composition. Quick sketch:
- lib/sync
|- clients/
|- concerns/
|- faye_extension.rb
|- base.rb
|- dummy.rb
|- faye.rb
|- pusher.rb
|- stomp.rb
|- helpers/
|- concerns/
|- controller_helpers.rb
|- model_actions.rb
|- etc
|- interactors/
|- partial_creator.rb
|- refetch_partial_creator.rb
|- refetch_partial.rb
|- renderer.rb
|- trackers/
|- base.rb
|- erb.rb
This is very rough, and I won't speak to how accurate it is, but I think that it should be ironed out before trying to enable a conventions-based plugin architecture. Just a little bit of reorganization could go a long way.
- I think that minitest is becoming a bit burdensome as a test framework for this project. I'm usually quite impartial with regards to choices here, but
rspec-rails
would really make the suite more flexible and reusable. Something like rubocop would help clean up the existing codebase style and enable people to more readily contribute. I would also recommend using FactoryGirl to DRY things up and reduce/remove reliance on fixtures.
Those are my most immediate general thoughts. I wouldn't mind working through some of these thoughts in a follow-up pull request or two, but I think it would be a bit much for me to take on by myself. I would like to see this PR get merged first so that it's integrations aren't lost in the mean time. After that, I'd love to collaborate on this, as I'm actively using this gem and kicking off it's usage in another project with this STOMP adapter.
Sorry to dump so many thoughts on you, but drop your two cents in when you have a chance.
It's definitely worth the time, so let me know. Cheers.
@chrismccord is there anything I can do in the short-term to help get this merged?
I understand there are some merge conflicts due to recent changes, but I'm still looking for general feedback on how to get this PR merged. @chrismccord or @ajb, feedback and advice for resolving merge conflicts, please?
Thanks, cheers.
Heya @aeberlin,
Sorry for the delay. I'm onboard with a lot of your ideas in the long comment above. In fact, I'd like to try and outline a rough plan for the next major version of sync
, (which, by the way, will need to be renamed [#215]), but I haven't found the time to do so yet.
Anyway, I don't want to let that get in the way of this PR. This PR looks solid, and if you can resolve the merge conflicts, I can commit to taking the time to review & merge.
Great, thanks @ajb. Will start working through the conflicts.
@ajb Think I've resolved all the conflicts cleanly. Please review when you have a chance.
After looking over recent changes, I've noticed some similarities in the config keys for pusher and stomp, namely the websocket references. Do you have any thoughts on trying to generalize the pusher_
-specific keys for more familiarity and flexibility across adapters? Not sure if we want to tackle that in this PR, but still curious.
Will check back after travis builds complete in case I missed something. Cheers.
@ajb Please restart this job when you get a chance, issue doesn't look related to the changes.
https://travis-ci.org/chrismccord/sync/jobs/108574596
This looks great; just added a few inline comments above.
Can you comment on some of the changes around the initialization, onReadyInterval
, onConnectInterval
, etc? Were they necessary for STOMP, or just refactoring?
@ajb,
With regards to the coffee initialization process, I think I can simplify it by requiring that sync dependencies be loaded explicitly, without auto-loading themselves. If we can require a minor breaking change which enables sync to initialize itself explicitly, instead of on require, initializing itself and binding to window
, etc., it will allow me to omit those changes. Thoughts?
Overall reasoning was because of a race condition with dependencies I experienced locally. Not a huge deal, but it made me look at things a bit differently.
@ajb I still need to root out some issues with the debug_flag
and stompjs
, but do you see anything lingering still that needs to be addressed?
Looks good! The only big thing remaining is the initialization process & intervals... you say there was a race condition that you were experiencing locally? Maybe I can look into that for you?
I would also be fine with this, if you think it will be an improvement:
With regards to the coffee initialization process, I think I can simplify it by requiring that sync dependencies be loaded explicitly, without auto-loading themselves. If we can require a minor breaking change which enables sync to initialize itself explicitly, instead of on require, initializing itself and binding to window, etc., it will allow me to omit those changes. Thoughts?
Since we'll be releasing 1.0.0 (under a different name, too), now would be the time to make breaking changes.
@ajb,
The race condition was due to order of dependencies in sprockets. I took a stab last night at removing the auto-initialization and found that it was more complicated to include via sprockets than I had thought before. Having said that, I think that using the intervals is the best way to go, as it allows the Sync
coffeescript to initialize (and later connect) itself fully as soon as things are ready and available.
Thoughts?
I see a couple of potential issues with the current implementation of setInterval
:
-
setInterval(fn, 250)
waits 250ms before callingfn
, instead of calling it immediately. We want everything loaded as soon as possible. - The
onReadyInterval
variable inview_helpers.rb
is leaking into the global scope. We should wrap everything in an anonymous function, and use thevar
keyword.