Lotus v0.5.0 roadmap

Lotus v0.5.0

Roadmap

Release date: Sep 23, 2015

Features released so far: http://bit.ly/lotusrb-roadmap


Dear Community,
we want to continue with this exiciting journey, by announcing the plans for Lotus v0.5.0.

We have considered the idea of an architecture dedicated to HTTP API apps, made only of router + actions. But with our just released application architecture, you can build lightweight components to serve JSON payloads, bypassing the view. With this approach you can easily achieve a something similar to what lotus-api will be in the future.

We had to take a side, and we choose full featured web applications for this next release.

WebSocket

We wanted to introduce this feature since last year, but unfortunately we had to postpone it because basic, necessary features weren’t delivered yet. Now it’s the time to ship them.

WebSocket is a W3c technology to achieve real-time, two-way communication between the server and the client. At the transport level it uses a full-duplex TCP connection to send packets back and forth.

In order to avoid data race conditions, most of the implementations outside depend on the Reactor Pattern. It’s a single-threaded way to achieve safe communication with clients. That means the choice of the application container is restricted to the servers who implement this pattern. Thin is one of them and it depends on EventMachine.

We’re rejecting this design, because Lotus is thread-safe since the first release, so we want to use raw connections and let our developers to take advantage of concurrent web servers like Puma.

Unfortunately Rack protocol doesn’t provide a clear specification on how sockets must be handled. With their 1.5 release, there was an introduction of a hack (Rack Hijack) to overcome to this problem and expose a TCP connection. This object is kinda compatible with Ruby IO, and it may vary from server to server.

In order to use this feature, you must be able to use Rack 1.5+ and a concurrent web server.

We need to add websocket (or websocket-native) gem to our Gemfile and to enable the feature.

# apps/web/application.rb
module Web
  class Application < Lotus::Application
    configure do
      # ...
      websocket true
    end
  end
end
# apps/web/controllers/chat/show.rb
module Web::Controllers::Chat
  class Show
    include Web::Action
    
    def call(params)
      websocket.on_open do
        send_data "Hi"
      end

      websocket.on_message do |message|
        send_data "Echo: #{ message }"
      end
    end
  end
end

Here’s the client side code:

document.addEventListener("DOMContentLoaded", function(event) { 
  var socket       = new WebSocket("ws://localhost:2300/chat");
  
  socket.onmessage = function(message) {
    console.log(message);
    window.alert(message.data);
  };
  
  socket.send("Hello");
});

Assets

Another step in the direction of full featured web applications is to provide support for assets.

When in development mode, Lotus already serves all the files placed under public/.

With the upcoming release, we’ll introduce new helpers javascript and stylesheet, to link local or remote assets.

It will support preprocessors like SASS and all the template engines supported by Tilt. Developers will be able to specify source paths for assets and Lotus will find, preprocess and write them locally so the can be served to the browser.

We strongly encourage to write JavaScript code compatible with ES6, which can be preprocessed by Babel.

For the deployment stage there will be a new CLI command lotus assets, which will able to preprocess all these sources and place in the assets/ directory to be served staticall by your web server (eg. NGinx).

Our final goal is to have really fast deployments. For this first release, the assets will NOT be compressed and merged. We are evaluating solutions to make browsers happy and keep fast deployments.

Mailers

We’re partner of Rails Girls Summer of Code, which is a program that encourages students to contribute to Open Source. We’re thrilled to work with DEIGirls team. Welcome Inês and Rosa!

They will work over the summer to a new gem in Lotus toolkit: lotus-mailer.

By following our philosophy, this library will offer both standalone functionalities in order to use it with existing Ruby applications, and at the same time it will have an integration with Lotus applications.

Let’s have a look at an example:

# lib/bookshelf/mailers/subscription_mailer.rb
module Bookshelf
  class SubscriptionMailer
    include Lotus::Mailer

    from    "<noreply@example.com>"
    subject "[Bookshelf] Invoice"
    to   -> { user.email }
    
    def prepare
      mail.attachments['invoice.pdf'] = invoice.to_path
    end
    
    def full_name
      "#{ user.first_name } #{ user.last_name }" 
    end
  end
end
# lib/bookshelf/mailers/subscription_mailer.text.erb
Hello <%= full_name %>,
Here's your invoice.

Come to visit us again at: <%= routes.home_url %>.
# # lib/bookshelf/mailers/subscription_mailer.html.erb
<p>Hello <%= full_name %>,</p>
<p>Here's your invoice.</p>
<br>
<p>Come to visit us again at: <%= routes.home_url %>.</p>

Then we can deliver it.

user    = UserRepository.find(1)
invoice = InvoiceRepository.last_by_user(user)

Bookshelf::SubscriptionMailer.deliver(user: user, invoice: invoice)

This will send a multipart email to the user with an invoice attachment.

Associations

Entity associations are an highly requested feature that we are happy to include.

You can define them in the mapper like this:

collection :author do
  entity     Author
  repository AuthorRepository
  
  attribute   :id,    Integer
  association :books, [Book]
end

Then we can use it to preload the associated records.

class AuthorRepository
  include Lotus::Repository
  
  def self.find_with_books(id)
    query do
      where(id: id)
    end.preload(:books).first
  end
end

So we’ll be able use like this:

author = AuthorRepository.find_with_books(1)
author.books # => a collection of books

Experimental Code Reloading

Lotus doesn’t implement code reloading itself.
It behaves like any other Ruby library, when required it’s immutable.

In order to provide code reloading in dev mode we use shotgun gem. It forks the current Ruby process and as result you have the just changed code available for the next request made by the browser.

Shotgun is great, but it has some problems: it isn’t compatible with JRuby, doesn’t work with NewRelic gem and because it’s Ruby it isn’t fast like we expected.

We want to keep the immutable core with a reloadable shell approach, by replacing Shotgun with entr.

It’s a POSIX compatible tool written in C with the purpose of observe the file system and make changes from source code available.

This has a few advantages: it’s faster and it will eliminate yet another Rubygem dependency for lotusrb.

You won’t need code reloading on CI or production, right? :slight_smile: So it’s useless to install that gem without even use it.

This will increase the complexity of the setup for developers. You will need to install it via apt-get or brew only once in the lifetime of your computer and you’re done. This will make Lotus processes lighter and CI/deployment times a little bit faster.

I’ve tested it manually on my computer and seems to work great. We do NOT discard Shotgun yet, but we want you to try entr, via lotus server --experimental-reloading.


IMPORTANT: we aim to finish these features by the end of August 2015, in order to let you to try it and report last-minute bugs. We don’t thing that a Release Candidate is necessary when under 1.0, but please help us to test them.

In case you want to contribute, please ping us in chat!


4 Likes