tinco / ruby_go_game_server

MIT License
3 stars 0 forks source link

Invoking the reactor across threads is broken #1

Open ioquatix opened 4 years ago

ioquatix commented 4 years ago

https://github.com/tinco/ruby_go_game_server/blob/e1e71c08afd080ddcdf324ff186542683187b606/lib/ruby_go_game_server/query_handler/message_queue_listener.rb#L19

If you want to do this you'll need to use some kind of message queue. Maybe we should provide this out of the box as part of async gem.

tinco commented 4 years ago

Hi @ioquatix ! Fancy seeing your here :D

Ah because #receive_message directly invokes #write on all the connections in its thread. So it didn't throw any errors, but I suppose that it'll have concurrent write race conditions?

Having some sort of buffer that the messages get appended to that is managed by the writing thread makes more sense anyway I feel. Just a plain Array would work fine in my opinion, and the API would not change because it's the #receive_messages concern that it gets invokes on different threads right? We could also make the object an actor.. anyway I don't see what sort of functionality you would add to async for this.

Btw how'd you stumble upon this one? I wrote this as a quick example to illustrate a talk I did at a Ruby meetup to inspire people to use Ruby for non-rails sort of stuff. It's got this weird overdesignedness to illustrate CQRS.

ioquatix commented 4 years ago

Occasionally I check things that depend on async using GitHub's dependency analysis. It's aways interesting to see how programmers are using async and the kind of mistakes they might be making, it informs my decision making process.

Regarding the thread safety issues, you will probably end up corrupting the underlying write buffer if invoked from multiple threads.

If the write becomes blocking, it may fail completely since you are not doing the write in the context of the reactor. The only way to do this correctly is to transit the request across the thread/reactor barrier, and in order to do this we need some thread-safe queue (like a channel).