ruby-hyperloop / hyper-react

The project has moved to Hyperstack!!
https://hyperstack.org/
MIT License
285 stars 14 forks source link

Production mode #191

Closed noma4i closed 6 years ago

noma4i commented 7 years ago

App works well in development. Right after Im trying to run it in production mode this prevents it from starting up

uninitialized constant React::Component

ruby: 2.2.1 rails: 5.0.0.1

Any clue?

App was generated by bundle exec rails g hyperloop:install --all Webpack installed and work as intended but only in dev ;(

catmando commented 7 years ago

Where is that error coming up? On the JS console? If so try adding this to the url query params: ?no_prerender=1 (this will turn off prerendering)

I tried it without webpack and could not reproduce the error.

However I am not sure why webpack in production would create that error...

I'll check around, I know we have an app in production using webpack, so I will see what the settings are.

ALSO ... any chance you could just push this to a repo? Might be quicker that way.

catmando commented 7 years ago

Okay not sure if this will help as I can't reproduce your problem exactly, try this (this is what we are using in production and it seems to work:)

1) in application.rb comment out the two lines that eager/autoload component views

    # config.eager_load_paths += %W(#{config.root}/app/views/components)
    config.autoload_paths += %W(#{config.root}/app/models/public)
    # config.autoload_paths += %W(#{config.root}/app/views/components)

2) then app/models/models.rb add a guard around the require_tree (as models are eager loaded)

# app/models/models.rb
require_tree './public' if RUBY_ENGINE == 'opal'

Give that a whirl and report back sir!

noma4i commented 7 years ago

Issue was while trying to do RAILS_ENV=production bundle exec rails s After fiddling with autoload paths Im able to start the app hence ruby process is about 90% cpu while page never loads and went to puma server self kill cause of timeout. Guess this is other issue. Will report if I will be able to start app in production mode on remote server.

webpack was mentioned as a part of installation but never affects the app. Issue was with rails app not able to get thru

catmando commented 7 years ago

If u can give access to your repo we might be able to quickly diagnose the problem... Either way stay in touch

noma4i commented 7 years ago

Ok. All good. Guide for some who will face same issues and will ignore docs:

  1. Generators are busted and not production ready(need RUBY_ENGINE to be added)
  2. Eager load paths from generator doesn't work in prod(follow fix by @catmando)
  3. Make sure you have precompiled assets and they include component
  4. Generator will add Allow All policy wich is scoped to development. You need add your policies or face 500 in /rr

Last thing left to fix is that production running app with connected action cable is not pushing anything to frontend while I can see HyperMesh::ActionCableChannel transmitting in development.

BTW there is no way to get rid of React Browser Context Initialized noise in console.

zetachang commented 7 years ago

BTW there is no way to get rid of React Browser Context Initialized noise in console.

Actually some of the log & warning we output in console should be removed in production environment.

catmando commented 7 years ago

@noma4i - thanks a lot!

1+2) I raised https://github.com/ruby-hyperloop/hyper-rails/issues/4 in hyper-rails... FYI if would like to contribute this would be an easy PR... otherwise we will get it fixed in an upcoming point release.

3) Not sure about the precompiling of assets comment. Is this being caused by the way we are doing things, or is it just stuff people need to know when going into production?

4) This is on PURPOSE. Otherwise people might not realize that they are opening up complete access to their public models. One possible way out of this is https://github.com/ruby-hyperloop/hyper-rails/issues/5

I think the reason action-cable is not working is because rails 5 default configuration (see cable.yml) looks like this:

development:
  adapter: async

test:
  adapter: async

production:
  adapter: redis
  url: redis://localhost:6379/1

I have also raised issue https://github.com/ruby-hyperloop/hyper-react/issues/193 regarding turn off messages in production

Given the issues are covered elsewhere do you agree we can close this?

noma4i commented 7 years ago

@catmando Action cable setup done right. Iv recorded footage where you can see:

Addition:

What if it's not action cable issue? Iv switched to simple_poller instead. Can see how it's polling. Let's try and create record to be pushed to component. Nothing happened.

I was monitoring synchromesh_queued_messages table in DB. There no records inserted there. So I can say that issue comes not from transporting messages via action_cable/simple poller.

TLDR: Development ENV:

1   --- https://124.194.132.1/rr/ ...   0
catmando commented 7 years ago

@noma4i to confirm - you are saying your App does not work in production even when using simple-poller?

Most odd.

You are correct that in polling mode all messages get shoved in the queued_messages table. But for all other modes that table is only used during initial startup to capture events between the request, and by the time page completes loading.

We are using pusher in production currently. But there should be no difference, as you have seen So I will do a little playing here, and talk to @adamcreekroad about any settings he had to make.

catmando commented 7 years ago

@noma4i to confirm - you are just testing using the console per your video?

If so that may be the problem.... I will check it out...

noma4i commented 7 years ago

@catmando Simple Poller setting doesn't lead to queuing messages. Feels like no callback on record save was executed. Maybe issue with exposing model as public?

Video recorded with full setup rails+postgres+redis+puma(2 workers) deployed. While testing Im following tutorial when Im able to create record from rails console and see the actual result to be pushed to the client.

Statements:

catmando commented 7 years ago

@noami hmmm... just tried it with simple poller example app in production... no issues

could you try this please:

open two browser windows...

go into one browser console and then enter Opal.Word.$create(Opal.Hash.$new({text: "blah"}))

(assuming your model is called Word, and you have a attribute called text)

trying to see if this problem with rails console communicating updates, or more fundamental.

noma4i commented 7 years ago

Looks strange that development is able to serve while production env fails. In despite of issues with eager loading/opal_env which prevented whole app from starting in prod I can see other production specific issues which Im not able to debug.

Current debug state is:

catmando commented 7 years ago

you can also try this:

HyperMesh::Connection.active

in the rails console

it should return something like ['application']

noma4i commented 7 years ago

Opal.Word.$create(Opal.Hash.$new({text: "blah"})) - works perfect. Records are appearing in component and in Database.

 HyperMesh::Connection.active
        (0.6ms)  SELECT "synchromesh_connections"."channel" FROM "synchromesh_connections"
       ["Application"]
catmando commented 7 years ago

great... and do you see it updating a second browser?

noma4i commented 7 years ago

yep. 1 window where Im doing js console command will update second incognito mode window on the same page. Channels are in sync.

catmando commented 7 years ago

great... this means the problem is just with console communicating with server, which has been a big pain to get working.

catmando commented 7 years ago

okay I am going offline...

noma4i commented 7 years ago

Thnx for live debug!

catmando commented 7 years ago

did you say console is on a different server? that could be the problem

noma4i commented 7 years ago

1 app, 1 server, 1 database. Rails console executed via ssh.

catmando commented 7 years ago

hmmm... what happens is console sends http message to server, that it has updated the DB...

catmando commented 7 years ago

what do you see if you do HyperMesh::Connection.active in the console?

noma4i commented 7 years ago
> HyperMesh::Connection.active
(0.6ms)  SELECT "synchromesh_connections"."channel" FROM "synchromesh_connections"
["Application"]
catmando commented 7 years ago

that is correct

catmando commented 7 years ago

okay I do have to go... perhaps we can debug more later tonight or tomorrow... what Timezone are you?

catmando commented 7 years ago

also I think as you can see this is just a problem with console interacting... actual browser updates are working properly

catmando commented 7 years ago

gotta go though

noma4i commented 7 years ago

Now I can clearly say this is rails console issue. To prove that Iv done:

Conclusion: rails console is out of sync with ReactiveRecord

catmando commented 7 years ago

okay good.

Here is what happens: Only the server itself can broadcast push notifications. So when you make a change on the console, the console does an http post to the server, letting it know what to send. The server gets this info and then does the broadcast.

So please try this in the console:

HyperMesh::Connection.root_path

you should get back the URL of the server... Let me know what it is...

if you do get a URL can you ping that URL from the console?

You can try this HyperMesh.send_to_server('Application', []) you should see the http request to /rr/console_update coming in...

FYI - thanks for all the information you have provided!

noma4i commented 7 years ago

Pushing things from console are not real life example. My concerns were that Im not able to go thru example app and replicate things from doc.

I was wondering will Sidekiq work then. As for development env it works. Will do production testing where Word will be created from inside Sidekiq worker. Reallife use case: 2 VMs where one serves rails app front while second will do sidekiq queue. If things were created by sidekiq(ex: log entry) RailsFront should serve component with data.

catmando commented 7 years ago

@nomai4i - Well the console should work, and I do not like mysteries. Where there is smoke there may be a fire. If at any point you can spare some time to figure out why that does not work, please let me know / try the things I suggested.

I just did an experiment to make sure separate ruby processes can update the data base and it works fine, but you have to have redis or production pusher configuration. Polling, actioncable async, and pusher-fake will not work as these all depend on broadcasting out of the main rails application.

That is why the HyperMesh module checks if it running in the console, and if so does a post back to the main rails application, because often in the console you will be using actioncable-async, polling, or pusher-fake.

You could also try this in the console for a clue: type def HyperMesh.on_console?; false; end this will fake out HyperMesh into thinking you are NOT on the console.

then try Word.create(text: 'hello') and you should see the broadcast going out right from the console.

Let me know what you find.

noma4i commented 7 years ago

Latest testing with suggested override of on_console? was successful. Works as intended. Full console log:

def HyperMesh.on_console?; false; end
       def HyperMesh.on_console?; false; end
       :on_console?
Word.create(text: 'hello')
       Word.create(text: 'hello')
        (0.6ms)  BEGIN
       SQL (1.5ms)  INSERT INTO "words" ("text", "created_at", "updated_at") VALUES ($1, $2, $3) RETURNING "id"  [["text", "hello"], ["created_at", 2016-12-03 02:38:42 UTC], ["updated_at", 2016-12-03 02:38:42 UTC]]
        (0.9ms)  COMMIT
       SQL (1.0ms)  DELETE FROM "synchromesh_connections" WHERE (expires_at IS NOT NULL AND expires_at < '2016-12-03 02:38:42.731650')
       HyperMesh::Connection Exists (0.9ms)  SELECT  1 AS one FROM "synchromesh_connections" WHERE (refresh_at IS NOT NULL AND refresh_at < '2016-12-03 02:38:42.733707') LIMIT $1  [["LIMIT", 1]]
        (0.5ms)  SELECT "synchromesh_connections"."channel" FROM "synchromesh_connections"
       HyperMesh::Connection Load (0.9ms)  SELECT "synchromesh_connections".* FROM "synchromesh_connections" WHERE "synchromesh_connections"."channel" = $1 AND (session IS NOT NULL)  [["channel", "Application"]]
       HyperMesh::Connection Exists (0.6ms)  SELECT  1 AS one FROM "synchromesh_connections" WHERE "synchromesh_connections"."channel" = $1 AND "synchromesh_connections"."session" IS NULL LIMIT $2  [["channel", "Application"], ["LIMIT", 1]]
       [ActionCable] Broadcasting to synchromesh-Application: {:message=>:create, :data=>{:broadcast_id=>"47115386219200-1480732722.7465248", :channels=>["Application"], :klass=>"Word", :channel=>"Application", :record=>{:id=>40, :text=>"hello", :created_at=>Sat, 03 Dec 2016 02:38:42 UTC +00:00, :updated_at=>Sat, 03 Dec 2016 02:38:42 UTC +00:00}, :previous_changes=>{:id=>[nil, 40], :text=>[nil, "hello"], :created_at=>[nil, Sat, 03 Dec 2016 02:38:42 UTC +00:00], :updated_at=>[nil, Sat, 03 Dec 2016 02:38:42 UTC +00:00]}}}
       #<Word id: 40, text: "hello", created_at: "2016-12-03 02:38:42", updated_at: "2016-12-03 02:38:42">

You can see ActionCable transmission happens.

janbiedermann commented 6 years ago

with lap20 auto_config works well for development and production. action_cable also works. Closing this.