Monthly Archives: October 2018

Do you have a framework for dealing with emergencies?

Your ads will be inserted here by

Easy Plugin for AdSense.

Please go to the plugin admin page to
Paste your ad code OR
Suppress this ad slot.

Do you have a framework for dealing with emergencies?

In my pre-Arkency life, I worked for a corp.

Keep in mind that it was my very beginning of the commercial-IT world. I sometimes felt lost inside this huge DevOps machine. Lost and alone – as usually, when something breaks, there was nobody to ask for help.

It had to happen. One day, by accident, I ran some kind of a DB-clean-up script, with the wrong date, on production. The script’s job was to delete records that are old enough. While fiddling with the script, I changed the definition of records old enough to records visible today (not closed). And accidentally ran the script.

My reaction – a complete paralysis. I wasn’t even sure what the script exactly did. Unfortunately, I had never found time before to analyse the script line-by-line. Also, I have never seen unit tests, so most likely they didn’t exist.

So I had no idea how much damage I caused. Maybe the script had a protection from so accidental usage as mine? It should have, right?

I took a look at the frontend to see if everything is ok – it wasn’t. Literally no data for today. It was present a minute ago but disappeared. Cool. They will fire me.

One of the managers visited me quickly and brought to book:

Where are my data? I need it NOW for my work. When will you restore it?

I already realized that I had to call an ex-coworker of mine (he was currently on vacation, but I had no choice…) to get all needed information. So my answer was:

I don’t know. In the worst case scenario, when he is back, so next week [4 days].

The end of the story was pretty lucky, though. I immediately got an accurate instruction from my coworker-on-leave – there was a daily backup of the data, so probably all we need is a casual restore from /a_directory.

A half-hour of preparation, with an extra pair of eyes and triple-checking if this time everything is ok – and voilà! The records are back! Only a few of them were lost forever (those inserted after the backup), but come on! You can insert them again! We saved the day!

Sounds familiar?

Today, I’m not very proud of this situation. There were two good reactions, though:

  • The paralysis that mastered me after my fuckup. When you don’t really know how to fix things, it’s better to do nothing than to do anything with a panic and, most likely, only cause more damage. For instance, read the story about Unix recovery in 1986 and the comments.
  • Pair-fixing the issue.

What should I have done better?

Of course, easiest to say: You should simply don’t make such stupid things, but I’m afarid it’s impossible. We, in Arkency, are agreed – everyone makes mistakes. Smaller, larger, more or less foolish ones – but everyone does them. The professionalism doesn’t mean no mistakes, but rather as little mistakes as possible, asymptotically to zero; zero is unreachable.

Speaking of the art of professionalism – the true value of the developer is not how many mistakes they do, but how they recover.

What is a shame today?

Communication

It was my duty to tell the managers what happened. They shouldn’t have needed to visit me and inquire about the accident. I should have told them immediately:

  • What happened (all the data is lost because of my inattention)
  • I’m working on it
  • That’s my top-prio
  • However, I need help
  • I’m sorry

An apology is nice here (it was clearly my fault), but useless without all above.

If necessary, I should keep them informed about the progress. Luckily, the recovery was so quick that the next message was, at the same time, the last one: Hey, it’s ok now, we only lost today’s records.

Your ads will be inserted here by

Easy Plugin for AdSense.

Please go to the plugin admin page to
Paste your ad code OR
Suppress this ad slot.

But staying quiet is never a good option.

Estimation

I don’t know. In the worst case scenario, when he is back, so next week [4 days].

I didn’t lie. The problem is – such an information doesn’t tell very much. At the end of the day, the incident was solved after less than an hour! Why were the numbers so different?

Much better approach is to estimate with 3 values:

  • Optimistic – if literally everything goes without complications
  • Expected
  • Pessimistic – if literally everything goes wrong

So I should have told:

  • Optimistically, half an hour.
  • Realistically, 3 hours (The ex-coworker is on vacation, why should he bother?)
  • Pessimistically, 4 days (I can never catch him on the phone, never find a solution by myself, and solve it only after he comes back to work.)

All I did was telling only the third value. This was not the end of the world, if treated as an obligation (what the management often does). But the other two values were much less frightening, what should have been spoken.

Surprisingly, this time the most optimistic estimation was true. This happens very rarely, I consider this as a luck. Surely, next time my coworker won’t break his sunbathe.

A framework

That would be a dream. You have a list of things, step-by-step, what to do (and what not to do) in hard times. The list is very specific, but at the time it gives you some level of freedom in designated areas.

Handling emergencies is an individual matter. In depends very much on you as a programmer and as a developer, your habits, your team and your project. There are some hard rules here, like be verbose or give 3 values in estimations. However, it’s not exhaustive. There’s always a whole lot of unknowns.

You should have your own framework for such cases. Otherwise you are exposed to cases like this one above.

We described ours in Responsible Rails book.

Responsible Rails

Do you have a framework for dealing with emergencies?

Tired of weekend works? Missing a framework for handling emergencies? Looking for advice how to mitigate the number of production accidents?

Try Responsible Rails! The book contains:

  • over 100 pages
  • anwsers to the most crucial questions about being a responsible Rails developer
  • Arkency’s step-by-step execution on how to act when accident happens
  • 13 real-life stories writen by different authors
  • discussion about the stories, from diverse points of view
  • a portion of advice how to avoid emergencies as much as possible

Keep in mind that the book is still in beta stage.

Summary

Sometimes you can observe that you change the habits during emergency – maybe it’s time to reconsider your beliefs?

  • If you usually TDD, but drop it in emergency times – you don’t really trust TDD.

  • If you need a partner to fix an issue – well, maybe pair programming is a good idea also in the quiet times?

  • If you turn the music off to gain the maximum mana – why don’t you do it all the time?

  • If an acident shows that you can delay all the needless things (casual talks, facebook checkings, etc.) – take a look at Pomodoro Technique.

Testing Event Sourced application – the read side

Your ads will be inserted here by

Easy Plugin for AdSense.

Please go to the plugin admin page to
Paste your ad code OR
Suppress this ad slot.

Testing Event Sourced application - the read side

In my last post, I’ve presented a way how to test an Event Sourced application. But again (yes, again and again) some part was missing there. It is clearly visible when you look at test coverage:

Testing Event Sourced application - the read side

The missing part, of course, is the read side.

This application uses read model that are build by a set of event denormalisers based on an events published by write side (an Aggregate to be specific). Current flow is as follows:

  • Aggregate’s method produces a domain event
  • When command handler is about to finish it published all domain events produced by the aggregate to Event Store
  • Rails Event Store publishes received domain events to all subscribers that have been subscribed for a specific event type.
  • Denormalisers (in our application the subscribed event handlers) handle the domain event and prepare a read model so it could be easily and quickly read by a website.

The read model (a.k.a projection because it is a projection of domain events) should be build based on the set of domain events. The subset of domain events needed to handle depends on the needs, depends on which domain events have the impact on a projection state. The source of domain events could be a single aggregate’s stream, a class of streams (i.e. all streams of Order’s aggregates) or all domain events cherry-picked by a projection.

Given current state

How to build an initial state when you don’t have a state? This should be quite easy. Any state is a derivative of domain events. You could build any state by applying domain events.

To build a state you just need some events:

require 'test_helper'  module Denormalizers   class ItemRemovedFromBasketTest < ActiveSupport::TestCase     include EventStoreSetup      test 'remove item when quantity > 1' do       product = Product.create(name: 'something')       customer = Customer.create(name: 'dummy')       order_id = SecureRandom.uuid       order_number = "123/08/2015"       # arrange       event_store.publish_event(Events::OrderCreated.create(                                 order_id, order_number, customer.id))       event_store.publish_event(Events::ItemAddedToBasket.create(                                 order_id, product.id))       event_store.publish_event(Events::ItemAddedToBasket.create(                                 order_id, product.id))        # act ...        # assert ...     end   end end 

There is always a problem how initial state for a test should be build. With the use of event handlers it should be easy to build it – all you need is to define a set of domain events and pass them through the event handler.

When an event happened

Each event handler is a function: f(state, event) -> state In our case, the acting part of the test will be sending a domain event to an event handler and by knowing the initial state and payload of the domain event we could define our expected state.

require 'test_helper'  module Denormalizers   class ItemRemovedFromBasketTest < ActiveSupport::TestCase     include EventStoreSetup      test 'remove item when quantity > 1' do       # ...       # arrange       event_store.publish_event(Events::OrderCreated.create(                                 order_id, order_number, customer.id))       event_store.publish_event(Events::ItemAddedToBasket.create(                                 order_id, product.id))       event_store.publish_event(Events::ItemAddedToBasket.create(                                 order_id, product.id))        # act       event_store.publish_event(Events::ItemRemovedFromBasket.create(                                 order_id, product.id))        # assert ...     end   end end 

Expect stage change

There could be various types of event handlers. There is no one way of asserting the output. In this case, where event handlers (denormalisers) produce relational denormalised model the thing we check is if the model is build as expected.

require 'test_helper'  module Denormalizers   class ItemRemovedFromBasketTest < ActiveSupport::TestCase     include EventStoreSetup      test 'remove item when quantity > 1' do       product = Product.create(name: 'something')       customer = Customer.create(name: 'dummy')       order_id = SecureRandom.uuid       order_number = "123/08/2015"       # arrange       event_store.publish_event(Events::OrderCreated.create(                                 order_id, order_number, customer.id))       event_store.publish_event(Events::ItemAddedToBasket.create(                                 order_id, product.id))       event_store.publish_event(Events::ItemAddedToBasket.create(                                 order_id, product.id))        # act       event_store.publish_event(Events::ItemRemovedFromBasket.create(                                 order_id, product.id))        # assert       assert_equal(::OrderLine.count, 1)       order_line = OrderLine.find_by(order_uid: order_id)       assert_equal(order_line.product_id, product.id)       assert_equal(order_line.product_name, 'something')       assert_equal(order_line.quantity , 1)     end   end end 

… or an exception?

No errors here – what has happened it has happened – you could not change the past. If you could not handle event you should fail? … or …

… or an event published

Some might ask: But what if we fail to execute our event handler? No exceptions? Then what? The answer is: more domain events 😉 The domain event is just a message. If you use queues, you might know how to deal with messages that could not be processed. There are several patterns: retry it, skip it, … and finally if you really could not do anything you will send that message to dead letter queue. Similar actions could be applied here, retry later if the previous message has not been processed yet, skip it if it has been already processed or publish a compensation message if your domain model should take some actions.

Sanitizing html input: youtube iframes, css inline styles and customization

Sometimes we give users tremendous power over the content generated on the web platforms that we write. The power to add content using HTML/WYSIWYG editors.

Sanitizing html input: youtube iframes, css inline styles and customization

There is only one gotcha. We need to make sure that this power is not abused by malicious users. After all, you are a responsible developer, right?

One of the libraries that you can use for that is the Sanitize ruby gem .

Sanitize.clean(html) 

Why it matters

  • Most importantly to avoid XSS attacks.

    You are probably already aware of them and know of the danger.

  • And to avoid CSS Injection attacks.

    They can be used to lead the customer to an unsafe page outside of your website without the customer being aware of that. Imagine that your shopping platform allows people to buy products. When people click a “buy” button somewhere outside a product description they might think they are still on your page. But malicious attacker can use CSS and HTML to place identically looking button at the same location on the page that your original button is placed on.

    User can click such button and be redirected to their own domain with layout identical to your shopping platform. They might think they are logging in or buying on your platform but instead they are providing their login and password or credit card credentials on the attacker page.

Youtube iframe

But sometimes you want to include or exclude some parts of the HTML conditionally. For example you might not want the user to be able to include all <iframe>-s but you might want them to be able to include youtube videos of cats or ted.com talks.

class IframeWhiteList   def initialize(src, attributes)     @src = src     @attributes = attributes   end    def call(env)     node      = env[:node]     node_name = env[:node_name]      # Don't continue if this node is already whitelisted or is not an element.     return if env[:is_whitelisted] || !node.element?      # Don't continue unless the node is an iframe.     return unless node_name == 'iframe'      # Verify that the video URL is actually a valid video URL.     return unless node['src'] =~ @src      # We're now certain that this is a valid embed, but we still need to run     # it through a special Sanitize step to ensure that no unwanted elements or     # attributes that don't belong in a YouTube embed can sneak in.     Sanitize.clean_node!(node, {       :elements => %w[iframe],       :attributes => {'iframe'  => @attributes}     })      # Now that we're sure that this is a valid embed and that there are     # no unwanted elements or attributes hidden inside it, we can tell Sanitize     # to whitelist the current node.     {:node_whitelist => [node]}   end end  class YouTubeWhiteList < IframeWhiteList   def initialize     super(       //A(https?:)?////(?:www/.)?youtube(?:-nocookie)?/.com///,       %w(         allowfullscreen frameborder height src width scrolling         webkitallowfullscreen mozallowfullscreen         style title id name seamless         allowtransparency hspace vspace marginheight         marginwidth border       )     )   end end  Sanitize.clean(@html, Sanitize::Config::RELAXED.merge(transformers: [   YouTubeWhiteList.new,   TedCom.new ]) 

Be very careful when defining the regexp for the URL and make sure to write some tests. If you forget to escape one character (for example a dot) the attacker can embed an iframe from similarly looking domain.

let(:html) do   %q{     <iframe src="//wwwXyoutube.com/embed/IqajIYxbPOI"></iframe>     <iframe src="//www.youtubeXcom.com/embed/IqajIYxbPOI"></iframe>     } end it { expect(html_description.sanitized.strip).to eq("") } 

And be careful to write tests for the attributes:

let(:html) do    %q{<iframe width="560" height="315" src="//www.youtube.com/embed/IqajIYxbPOI"               frameborder="0" allowfullscreen style="box-sizing: border-box;">       </iframe>      } end it { expect(html_description.sanitized).to eq(    %q{<iframe width="560" height="315" src="//www.youtube.com/embed/IqajIYxbPOI"               frameborder="0" allowfullscreen>       </iframe>    } ) } 

Allowing inline styles

For allowing certain styles you might want to use HTML::WhiteListSanitizer that comes from your Rails 4.1 or Rails::Html::WhiteListSanitizer from rails-html-sanitizer gem in later versions (which under the hood uses loofah gem).

Allowing and sanitizing inline styles might be required for your editor to work properly.

class CssStyleCheck   class Sanitizer < HTML::WhiteListSanitizer     self.allowed_css_properties = HTML::WhiteListSanitizer.       allowed_css_properties + %w(border-style border-width)   end    def initialize     @sanitizer = Sanitizer.new   end    def call(env)     node      = env[:node]     node_name = env[:node_name]     return if env[:is_whitelisted] || !node.element? || !node['style']     node['style'] = @sanitizer.sanitize_css(node['style'])   end end   Sanitize.clean(html, Sanitize::Config::RELAXED.merge(transformers: [   CssStyleCheck.new, ]) 

Make sure to test it as well. I usually test that all allowed attributes/styles are left unchanged and some of the disallowed (after all the list is infinite…) are removed:

let(:html) do   %q{<div style="background-color: 1px; border-bottom-color: 1px;"></div>} end it { expect(html_description.sanitized).to eq(html) } 
let(:html) do   %q{<div style="background-color: black; min-width: 10px;                  mso-pagination:none; box-sizing: border-box;">      </div>     } end it { expect(html_description.sanitized).to eq(    %q{<div style="background-color: black;"></div>}) } 

Relaxing even more

Even though the list of HTML tags and attributes allowed by Sanitizer is quite long, you might still want to customize it a bit depending on your needs and the way the editor of your choice works.

def self.relaxed_config_hash_deep_copy   Marshal.load(Marshal.dump(Sanitize::Config::RELAXED)) end  Config = relaxed_config_hash_deep_copy.tap do |config|   config[:elements]            += %w(hr)   config[:attributes][:all]    += %w(border)   config[:attributes]["a"]     += %w(target) end.freeze  Sanitize.clean(html, Config) 

Note

The examples are using sanitize in version 2.1.

Did you like this article? You might find our Rails books interesting as well .

Sanitizing html input: youtube iframes, css inline styles and customization Sanitizing html input: youtube iframes, css inline styles and customization Sanitizing html input: youtube iframes, css inline styles and customization Sanitizing html input: youtube iframes, css inline styles and customization Sanitizing html input: youtube iframes, css inline styles and customization Sanitizing html input: youtube iframes, css inline styles and customization

CQRS example in the Rails app

CQRS example in the Rails app

Recently I have worked in a new project for some time. We implement an application where one functionality is to show an organization’s (tree-like) structure. The structure contains information about relations between employees. I have been thinking how to build this feature. I was wondering if I should go typical way implementing all CRUD actions. In this case I would have to generate the structure for each call. I thought It will be faster. It is a startup. So until the project is young performance is not a problem. Although after few syncs we decided to go an another way.

I am fascinated by the DDD and CQRS approaches. In Arkency we are used to saying that every time we return to the “Implementing DDD” book we realize that it has answers to all the questions and doubts. So going back to the feature we decided to implement the structure as a Read Model.

Example

I love examples so I will not leave you hanging. Our app is split into two parts. We have a frontend implemented in React and a Rails backend. I will focus only on the backend part. If you are interested in how we deal with React you can read some of ours books. In next steps I will show you how we implemented simple CQRS. I will focus on building a Read Model using events.

Starting from the top. The following example shows the controller with basic actions. As you can see we simply call Application services where each one has a separate responsibility. In clean CQRS we should use Commands. We will refactor it in a next step.

 class TeamsController < ApplicationController   before_action :authenticate_user_from_token!    def in_organization     teams = AppServices::TeamsInOrganization.new.(params[:organization_id])     render json: { teams: teams }   end    def show     AppServices::GetTeam.new.(params[:id])   end    def create     AppServices::AddNewTeam.new.(params[:team])   end    def update     AppServices::EditTeamData.new.(params[:team])   end    def destroy     AppServices::RemoveTeam.new.(params[:id])   end end 

The following example shows one app service. We use this service to create new a Team.

 module AppServices   class AddNewTeam     include EventStore::Injector      def initialize(team_repository = ::OrganizationBc::Adapters::TeamRepository.new)       @team_repository = team_repository     end      def call(team_data)       team = create_new_team(team_data)       publish_team_created(team_data, team.id, parent.department)       team     end      private     attr_reader :team_repository      def create_new_team(team_data)       add_new_team = OrganizationBc::Teams::Services::AddNewTeam.new(team_repository)       add_new_team.(team_data)     end      def publish_team_created(team, team_id, department)       stream_name = "team/#{team_id}"       event = ::Event::TeamCreated.new({                                            data: {                                                team: {                                                    id:              team_id,                                                    organization_id: team[:organization_id],                                                    name:            team[:name],                                                    parent_id:       team[:parent_id],                                                    department:      team[:department],                                                    type:            'team'                                                }                                            }                                        })       event_store.publish_event(event, stream_name)     end   end end 
 module OrganizationBc   module Teams     module Services       class AddNewTeam         def initialize(repository)           @repository = repository         end          def call(team)           team = Team.new({             id:              team[:id],             name:            team[:name],             organization_id: team[:organization_id]           })           repository.create(team)         end          private         attr_reader :repository       end     end   end end 

I have chosen a simple service to focus on most important parts. As you can see we call a domain service to create Team model and save it into the Database. Team is an aggregate root in relation Team <-> Members. After creating a Team we publish event to the Event Store. We use our own Event Store called RailsEventStore. You can check out the github repository. Publishing event should be placed in aggregate but It was a first step to put in an app service. We don’t use the Event Sourcing. We decided to save a „current” state for now. Event Sourcing is a completely orthogonal concept to CQRS. Doing CQRS does not require event sourcing. But we save all events so It will be very ease to build an aggregate’s state using events.

We inject the EventStore instance using a custom injector. The whole setup you can see bellow.

 module EventStore   module Injector      def event_store       @event_store ||= Rails.application.config.event_store     end    end end 
 Rails.application.configure do   #other stuff   config.event_store = EventStore::SetupEventStore.new.() end 
 module EventStore   class SetupEventStore      def call       event_store                     = RailsEventStore::Client.new       structure_read_model            = OrganizationBc::ReadModels::Structure.new       event_store = config_structure_handler(structure_read_model, event_store)       event_store     end      private      def config_structure_handler(structure_read_model, event_store)       events = ['Event::OrganizationCreated',                 'Event::MemberAdded',                 'Event::MemberUpdated',                 'Event::MemberDeleted',                 'Event::MemberUnassigned',                 'Event::TeamCreated',                 'Event::TeamUpdated',                 'Event::TeamRemoved']       event_store.subscribe(structure_read_model, events)       event_store     end   end end 

So the Write part is almost done. In the SetupEventStore class we define event handler called OrganizationBc::ReadModels::Structure for our Read Model. We subscribe it to handle set of events.

 module OrganizationBc   module ReadModels     class Structure       def initialize(repository = ::OrganizationBc::Adapters::StructureReadModelRepository.new)         @repository = repository       end        def handle_event(event)         case event.event_type           when 'Event::OrganizationCreated'             create_structure_for_organization(event.data[:organization])           when 'Event::MemberAdded'             update_structure(event.data[:member]) { |structure, member| add_member_to_model(structure, member) }           when 'Event::MemberUpdated'             update_structure(event.data[:member]) { |structure, member| update_member_in_model(structure, member) }           when 'Event::MemberDeleted'             update_structure(event.data[:member]) { |structure, member| remove_member_from_model(structure, member) }           when 'Event::MemberUnassigned'             update_structure(event.data[:member]) { |structure, member| remove_member_from_model(structure, member) }           when 'Event::TeamCreated'             update_structure(event.data[:team]) { |structure, team| add_team_to_model(structure, team) }           when 'Event::TeamUpdated'             handle_team_updated(event)           when 'Event::TeamRemoved'             update_structure(event.data[:team]) { |structure, team| remove_team_from_model(structure, team) }         end       end        private       attr_reader :repository        def create_structure_for_organization(organization)         save_structure(organization[:id])       end        def update_structure(element)         org_structure = get_organization_structure(element[:organization_id])         yield(org_structure[:structure], element.merge!(children: []))         save_structure(element[:organization_id], org_structure)       end        def add_member_to_model(people, member)         if member[:parent_id] == ''           people.push member         else           people.each do |person|             if person['id'] == member[:parent_id]               person['children'] << member             else               add_member_to_model(person['children'], member)             end           end         end       end        def update_member_in_model(people, member)         people.each_with_index do |person, index|           if person['id'] == member[:id]             people[index] = member           else             update_member_in_model(person['children'], member)           end         end       end        def remove_member_from_model(people, member)         people.each_with_index do |person, index|           if person['id'] == member[:id]             people.delete_at(index)           else             remove_member_from_model(person['children'], member)           end         end       end        def add_team_to_model(people, team)         people.each do |person|           if person['id'] == team[:parent_id]             person['children'] << team           else             add_team_to_model(person['children'], team)           end         end       end        def handle_team_updated(event)         #code       end        def update_team_in_nodes(nodes, team)         nodes.map do |node|           if node['id'] == team[:id]             team[:children] = node['children']             team           else             node['children'] = update_team_in_nodes(node['children'], team)             node           end         end       end        def remove_team_from_model(people, team)         people.each_with_index do |person, index|           if person['id'] == team[:id]             people.delete_at(index)           else             remove_team_from_model(person['children'], team)           end         end       end        def get_organization_structure(organization_id)         record = repository.find_by_organization_id!(organization_id)         {structure: record.model['structure'], departments: record.model['departments'], version: record.version}       end        def save_structure(organization_id, model = {structure: [], departments: [], version: 0})         repository.create(organization_id, model)       end     end   end end 

The organization’s structure is a tree structure. Each Team has relation to a parent member and collection of child notes. These nodes are team’s members. We modify the structure’s model and save in Postgres Database for each handled event. We save model in JSON representation. We save a new record in each update to keep whole change history. The following example shows how the repository looks like.

 module OrganizationBc   module Adapters     class StructureReadModelRepository       class StructureReadModel < ActiveRecord::Base         self.table_name = 'structures_read_models'       end        ReadModelNotFound = Class.new(StandardError)        def create(organization_id, model)         version = model[:version] + 1         model[:version] = version         record = StructureReadModel.new({ organization_id: organization_id, version: version, model: model})         record.save!       end         def find_by_organization_id!(organization_id)         record = find_by_organization_id(organization_id)         raise ReadModelNotFound.new if record.nil?         record       end        private        def find_by_organization_id(organization_id)         StructureReadModel.where(organization_id: organization_id).order(:version).last       end      end   end end 

When we have build Read Model the last step is to create query for fetching model. We have separate module called AppQueries where we keep all queries. So the Read part is only one class. That’s all.

 module AppQueries   class LoadOrganizationStructure      def initialize(repository = OrganizationBc::Adapters::StructureReadModelRepository.new)       @repository = repository     end      def call(organization_id)       repository.find_by_organization_id!(organization_id)     end      private     attr_reader :repository   end end 

Conclusion

I can only say that was great decision to start this way. Now I now that we save a lot of time on investigation performance problems in the future. Off course the most important thing is to choose if CQRS is a good starting point. If you have simple CRUD feature it will be unnecessary.

I didn’t focus on test part. I think It is a great subject for a separate post. If you are interested in testing event sourced app you can check this post.

All code used in this post you can find here.

Testing race conditions in your Rails app

Testing race conditions in your Rails app

From time to time, there comes a requirement in your application where you have to guarantee that something can be done at most X number of times. For example, only 15 people can subscribe to a course, only limited number of people can buy this physical or virtual product, only 200 people can go to a concert, etc. How do you test that this limitation actually work? And not only work but that it works under heavy load, when there are multiple customers trying to buy the last item because it is a hot event or the product is offered with a big discount?

You might think that testing it is hard, and maybe not worthy? But I found out that sometimes it is not so hard at all, and it might be simpler than you imagine. Sometimes, all you need is 4 threads to reproduce and fix the problem.

specify do   begin     expect(ActiveRecord::Base.connection.pool.size).to eq(5)     concurrency_level = 4      merchant  = TestMerchant.new     product   = merchant.create_product(quantity: concurrency_level - 1)      customers    = concurrency_level.times.map{ TestCustomer.new }      fail_occurred = false     wait_for_it  = true      threads = concurrency_level.times.map do |i|       Thread.new do         true while wait_for_it         begin           customers[i].buy_products([{quantity: 1, product: product}])         rescue Orders::CreateOrderService::Invalid           fail_occurred = true         end       end     end     wait_for_it = false     threads.each(&:join)      expect_fail_for_one_customer(fail_occurred)     expect_success_for_rest_of_customers(customers, product)     expect_product_not_oversold(product, concurrency_level)   ensure     ActiveRecord::Base.connection_pool.disconnect!   end end 

Let’s go step by step through this code.

expect(ActiveRecord::Base.connection.pool.size).to eq(5) 

By default Active Record connection pool can keep up to 5 DB connections. This can be changed in database.yml . This just checks if the preconditions for the test are what I imagined. That no developer, and no CI server has these values different.

concurrency_level = 4 

One DB connection is used by the main thread (the one running the test itself). This leaves us with 4 threads that can use the 4 remaining DB connections to simulate customers buying in our shop.

merchant  = TestMerchant.new product   = merchant.create_product(quantity: concurrency_level - 1) 

We instantiate a new TestMerchant actor which creates a new product with a limited quantity available. There are only 3 items in the inventory so when 4 customers try to buy at the same time, it should fail for one of them. Actors are implemented with plain Ruby classes. They just call the same Service Objects that our Controllers do. This code is specific to your application.

customers = concurrency_level.times.map{ TestCustomer.new } 

We create 4 customers in the main thread. Depending on what being a customer means in your system, and how many Service Objects it involves, you might want to do this in your main thread, instead of in the per-customer threads. Because, we strive to achieve the highest contention possible around buying the product. If you create your customer in the per-customer threads it might mean that one customer is already buying while another is still registering.

fail_occurred = false 

In one of the threads, we want to catch an exception that placing an Order is impossible because it is no longer in stock and remember that it occurred. We need to define the variable outside of the Thread.new do end block, otherwise it would not be accessible in the main scope.

wait_for_it  = true 

I couldn’t find a way in Ruby to create a thread with a block, without starting it immediately. So I am using this boolean flag instead. All the threads are executing a nop-loop while waiting for this variable to be switched to false, which happens after initializing all threads.

threads = concurrency_level.times.map do |i|   Thread.new do     true while wait_for_it     begin       customers[i].buy_products([{quantity: 1, product: product}])     rescue Orders::CreateOrderService::Invalid       fail_occured = true     end   end end  wait_for_it = false 

We create 4 threads in which 4 customers try to buy the product which can be purchased max 3 times. One of the customers should fail in which case we will set fail_occured to true. The first thread is created faster than the rest of them and remember that we want high contention. So we use true while wait_for_it to wait until all threads are created. Then main thread sets wait_for_it to false. That starts the buying process for those customers.

threads.each(&:join) 

We don’t know how long it will take for the threads to finish so we gladly wait for all of them.

expect_fail_for_one_customer(fail_occured) expect_success_for_rest_of_customers(customers, product) expect_product_not_oversold(product, concurrency_level) 

Then we can check all our expectations. One failure, three successes, and product not over-sold. These, of course, are very specific to your domain as well.

When building such test case it is very important to start with red phase when you go through red, green, refactor cycle. Without the race condition preventing method that you choose to implement the test should fail. If it doesn’t fail it means the contention you created is not big enough.

One more thing. This test has self.use_transactional_fixtures = false which means it will not run in a transaction (otherwise other DB connections from other threads would not see the records created by setup in the main testing thread). Your test is responsible for cleaning the database after running itself. I use database_cleaner with deletion strategy for that.

Did you like this article? You might find our Rails books interesting as well .

Testing race conditions in your Rails app Testing race conditions in your Rails app Testing race conditions in your Rails app Testing race conditions in your Rails app Testing race conditions in your Rails app

How can Rails developers benefit from reading the Arkency books?

How can Rails developers benefit from reading the Arkency books?

As a Ruby/Rails developer, you have so many books to learn from. The choice is sometimes too big which can lead to choice paralysis.

In this blogpost I’d like to focus on the different aspects of your developer life. There are so many skills to improve. The Rails skills are the obvious ones. But there’s much more than that. Working in a team, safe refactoring, well-structured frontend applications, communicating with other people, even blogging.

I’d like to explain how we’re helping with improving those skills with our Arkency books.

Rails applications

Big chances are that you’re working on Rails applications. Some of them are probably the ones, which are not so pretty. You’d like to improve them (Scout Rule anyone?) but it’s not clear how to do it. Also, it’s a risk – what if you break anything? Another typical problem is the tests taking ages to run (and often fail for random reasons).

This is exactly why we came up with the book called: “Fearless Refactoring: Rails Controllers”.

How can Rails developers benefit from reading the Arkency books?

Thanks to this book, you’ll be able to improve your Rails codebase with more confidence. You will become fluent with new abstractions, like service objects, repositories, adapters. Your tests will run faster, saving you and your team a lot of time (and money!).

Thanks to this book, you will know where all kinds of Rails code belong to. You will get more conventions to use, even in bigger Rails apps.

The book was released as 1.0 in December 2014. The techniques which are included are not related to any specific Rails version – they can be applied to all Rails apps. They will work with Rails 2, Rails 3, Rails 4 and Rails 5 versions just fine.

If you ever heart about Domain Driven Design (DDD), then this book is a great introduction to DDD in the context of Rails applications. It presents almost all of the DDD building blocks. It prepares you to think in more domain terms.

Buy Fearless Refactoring: Rails Controllers

JavaScript frontends for Rails apps

As Rails developers, we were happy writing just Ruby code, for many years. Nowadays, just Ruby is not enough. We need to build rich user interfaces, which are possible only in JavaScript.

A big part of the Ruby community went with CoffeeScript, while some stayed with JavaScript.

The community was also split between many different frameworks. Some of us went with Angular, some went with jQuery, some went with Ember. React.js is the new approach to building JavaScript components. Backed by Facebook, it’s trending now, for good reasons.

After many (sometimes unsuccessful) journeys with other frameworks, we felt in love with React.js. As Arkency, we were probably one of the first companies to adopt React.js fully (thanks Marcin!). Very quickly, all the Arkency developers noticed the clean structure which React provides and it was adopted in almost all of our projects.

We learnt a lot about how to combine React.js with a typical Rails application. As a result, we shared the experiences in the “Rails meets React.js” book.

How can Rails developers benefit from reading the Arkency books?

The book will teach you:

  • How to install and configure React.js in your Rails project.
  • Working with dynamic React based forms.
  • How to transform your view to React-managed components.
  • What you can use React.js for in your projects and how.
  • Detailed knowledge about how to use it and best practices to work with React.js, with examples.
  • How to test React components.
  • You will also get Ruby and CoffeeScript code for the examples.
  • And it begins with a tutorial so that you start with practical skills.

Animations with React.js is such a great topic that we decided to record and include 2 videos on this topic.

Buy Rails meets React.js

React.js by Example

We love working with React.js so much, that we also published another book on this topic – “React.js by Example”.

How can Rails developers benefit from reading the Arkency books?

This book doesn’t focus on the Rails integration. We wanted to share with you how to setup a separated (from Rails) React.js-based frontend.

This book is directed to people who are total React.js newbies. There are 12 typical examples implemented in React.js. Each of the examples is another chapter. Each example contains a narration on how one of us (from Arkency) approaches the development of a React.js component.

What’s more – you receive all the repositories for this book! You can browse the code, you can run the examples, you can tweak them.

After reading this book, you will be fully ready to approach a typical React.js component.

The examples are written in EcmaScript2015 and use webpack.

Buy React.js by Example

Which of our React.js books to choose?

Those books are very different. They teach you React.js in different ways. While the “Rails meets React.js” book is more Rails focused, it focuses on developing one component from a small one to a very complex widget.

The “React.js by Example” is focused on the starting point. It shows 12 examples, which are typical things you will start with.

Many of our readers bought both of the books and are happy with that.

If you need to choose just one – if you want to use React.js within an existing Rails ecosystem, then go for “Rails meets React.js”. If you are allowed to develop the frontend separately to Rails, then choose “React.js by Example”.

Working in a team, being remote/async, communicating with the customer

Many of us want to be happy in their Rails projects. We usually want less meetings, less bureaucracy, less stress. We want more freedom and we want to be working on features that are important.

Many of us want to work asynchronously – we know the times of the day when we are most effective. Many of us want to work remotely – not to waste time in commuting, have the freedom of traveling and have more time to spend with our families.

Many of us are scared to talk directly to the customers.

That’s why we wrote the “Developers Oriented Project Management” book. We want to share what we learnt and how we’re able to work remotely and asynchronously.

How can Rails developers benefit from reading the Arkency books?

This book explains all the above topics. We teach what are the requirements for the team to work remotely and asynchronously. We teach how to communicate with the customers in ways which are win-win. We teach how to deliver value to the project even in situation when there’s not enough time to finish everything.

We also explain the tools, which are helpful in async collaboration.

Buy Developers Oriented Project Management

Would you like to start blogging more about programming, Ruby, Rails?

If you follow our Arkency blog, you may have noticed that we’re quite active in blogging. Several people from our team share knowledge using this medium.

It wasn’t always like that. Before 2012 we didn’t even have a company blog and almost no people blogged frequently.

How did we change that? How can you start blogging?

Over time, I developed a blogging therapy. I used it internally to encourage people to blog more.

I have identified what are the biggest blocking points for developers to stop them from blogging – no time, perfectionism, the impostor syndrome, not having anything interesting to write about.

I took those blocking points and addressed them in a way that helped many developers unblock themselves and share more of their knowledge.

That’s what the “Blogging for busy programmers” is about.

How can Rails developers benefit from reading the Arkency books?

Thanks to blogging you’ll learn more (learning by teaching is the best way!), you will build your (or your company) brand.

What we found out was that blogging is a great tool for recruitment, for attracting new clients.

The book is still in the beta phase (35 pages), but it already addresses all the above blocking points. Buying it now gives you all future updates for free.

Buy Blogging for busy programmers

Refunds

We strongly believe in the value of all our books. We have over 1200 unique, happy customers of our books.

We have a 100% refund policy – if you feel that the book didn’t deliver you the value you expected, send us an email to dev@arkency.com and we issue a refund without asking any question.

The future offer

If you’re interested in learning something specific from us – let us know! We plan to write more and such feedback will help us decide which topics are most interesting to you.

Three most telling files in legacy Rails apps

Three most telling files in legacy Rails apps Photo available thanks to the courtesy of wackybadger. License: CC-BY-SA 2.0

When working in a consultancy agency the ability to work with legacy applications is necessary. Your clients very often come with their codebases. If the app is already in use a rewrite doesn’t sound like a good idea – it’s best to approach to make improvements incrementally.

But the truth is that this skill is very important for every Rails developer. Even if you’re working on your own projects or creating the Rails-based startup from scratch after some time your code will grow. Tests are very likely to become slower. There will be more and more implicitness within your code. You accept that because you are within the context for a long time. You know tradeoffs, assumptions and decisions – often you made them by yourself. It’s good to have skills to measure the situation and have some kind of guidelines to protect yourself from mistakes while refactoring.

In this blog post, I want to show you three simple techniques we use to get ourselves a solid starting point for working with legacy Rails apps. You will be able to apply it to projects you’re working on and improve your planning and refactoring thanks to it.

What can you do without reading the code?

There are some steps you can take while working with legacy Rails apps to get an idea what problem you’d likely face when working with them. They are great because they give you some kind of overview with a very little commitment – you don’t need to read the application code at all.

They may seem obvious to you. But having a structured approach (even in a form of a checklist) to those steps can be really beneficial for you.

Take a look at project’s Gemfile

This is the first step you can do when investigating a legacy app. Gemfile tends to be a great source of knowledge when it comes to Rails apps. Since Rails ecosystem is so rich, people are accustomed to not reinventing the wheel but using gems made by the community.

It’s especially true when the codebase was left by a Rails software shop. With codebases written by people with a smaller expertise you can still find code like external services integration reimplemented by previous codebase’s developers.

Gemfile can also provide you heuristic about how the code was made. With projects with many (like 80-90+ gems) gems within the Gemfile it’s likely you’ll see smells like dead code, gems included but unused (left after refactoring) and different approaches to structuring the same pieces of architecture (which is not that bad).

While reviewing the Gemfile, you should take a great focus about those things:

  • Gems that are used to implement generic application concerns (like authentication, batch jobs, file uploading).
  • Gems with duplicated responsibilities. Such situation often indicates that one of the gems are unused, or you should constrain the usage of such gems to one gem and drop the others.
  • Gems that introduce bigger DSLs. You should ask why DSLs is needed in the first place.
  • Custom vendor gems. If they aren’t simple they are first candidates to be discussed with the previous team or technical people on your client’s side.
  • Gems changing the programming model of the application like event_machine. They require different commitment and care while testing and refactoring – so you need to take this into consideration.

Take a look at db/schema.rb

Your applications usually are all about the data you store and process. Since by default Rails apps use relational databases, they maintain a schema. It is a great help when restoring the database structure on a new workplace. But it can also have benefits when it comes to analyzing legacy applications.

With schema.rb it is easy to see common smells with typical Rails apps:

  • God models – a.k.a. hundreds-line-of-code models. They are often naturally created near generic responsibilities of your app – User is the most common god model I’ve seen. Database models representing them also tend to be huge. By investigating the size of the table schema, you can take many assumptions about how complicated the representing model would be. Such models are often first targets of refactoring – but be careful since they also tend to be the most coupled ones.
  • Denormalised data. While denormalised data is not bad per se, it can be hard to refactor and rewrite features with denormalized schemas. They are often denormalized for performance reasons – it’s worth investigating whether such performance improvement is needed or not.
  • Non-existing indexes. They are the most common reason of database performance problems with Rails apps. If you see a table which has a natural candidate for an index (like title field or id field) but there is no index, adding it may be the first step to fix performance problems of such legacy app. Be sure to communicate when you create such migration – adding an index in a production database can be a very lengthy process.
  • Dead tables. You can always take the database table name (like users) and search the project for the conventional model counterpart (User) occurrences. You should also search for the table name itself since it can be connected with a model with a custom table name. It can be a very quick scan that will make dead code elimination much simpler – and eliminating dead code is one of the safest operations you can do in the legacy codebase.

Take a look at config/routes.rb

Routes file is another great source of knowledge when it comes to legacy Rails apps. If you treat a controller action as a C main method equivalent, taking a quick glimpse on routes can show you how complex in terms of starting points. This is an important measure. Apart from investigating a number of routes, you should take attention to following things:

  • Namespaces. Often they indicate that there was some effort in the past to create more modular segregation of the app. You can take it as a point of discussion with the client.
  • Auto-generated routes. They often indicate that there are routes and parts of the code that are beyond your control or you need to take an effort to do so. The best example here is a devise_for used by a popular authentication gem called devise.
  • Routing constraints. While not popular, they can change the flow of your app – so take care when you see them.
  • resources with only and except modifiers. It’s rather popular for Rails apps to have those modifiers when defining resources in routes. Such routes allow you to measure a number of potential queries (GET actions that only return data) and commands (POST/PUT/DELETE actions that modify the data) in the app. It’s another measure of a complexity of the legacy app.
  • Custom routes (using get / post / etc. methods). They indicate whether there is something in the app which is not a resource. You’d like to check whether it’s the case or not. It’s often an indicator of a missing concept in the app itself.

Summary

As you can see there is a lot that can be read without even touching the logic of a legacy app. Examining those three files helped us in a lot of situations – we got first points to discuss with clients and an overview what we can expect from an app itself.

Applying such analysis to your app can bring you many ideas and knowledge about what can be done to improve maintainability of it. I greatly encourage you to try it out – it can save you a lot of work later.

More

Did you like this article? You might find our Rails books interesting as well .

Three most telling files in legacy Rails apps Three most telling files in legacy Rails apps Three most telling files in legacy Rails apps Three most telling files in legacy Rails apps Three most telling files in legacy Rails apps Three most telling files in legacy Rails apps

Null Object pattern in practice

Null Object pattern in practice

Wikipedia describes Null Object as an object with defined neutral behavior.

Martin Fowler says Instead of returning null, or some odd value, return a Special Case that has the same interface as what the caller expects.

But null object pattern can also be seen as a way to simplify some parts of your code by reducing if-statements and introducing interface that is identical in both situations, when something is missing and when something is present.

Also it gives you a chance to properly name the situation in which you want to do nothing (is it always nothing?). By just adding Null prefix instead of using a more precise word, you are missing an opportunity.

There is a great Sandi Metz talk “Nothing is something” when she talks about it.

Rails View example

I have a view that is displaying an event data, as well as a collection of tickets available. It’s quite complicated view. It is reused in one different place. When the event organizer is editing event and tickets properties we display preview of the same page. So naturally we use the same view template that is used for rendering an event page for a preview page.

There are slight differences however so one additional variable (is_preview) is passed down through number of partials that the page is consisted of.

We have a class called EventPool which is responsible for gathering and keeping data to quickly answer the one question – whether a given ticket type is available to buy or not. In other words, it checks its inventory status. Naturally when organizers are in the process of adding tickets and haven’t saved them yet, they are still interested in seeing preview of how they would be displayed on event page. There is no point of checking inventory status of unexisting tickets (remember they are not saved yet). Also even for existing tickets we want to pretend they are not sold out when displaying the preview.

The code responsible for the situation (greatly oversimplified) looked like this:

# show.html.haml = render 'events/tickets', {     tickets: event.tickets,     event_pool: event_pool,     is_preview: is_preview   } 
# events/_tickets.html.haml - tickets.each do |ticket|   = render 'events/ticket', {        ticket: ticket,       ticket_pool: event_pool.pool_for_ticket_id(ticket.id),       is_preview: is_preview     } 
# events/_ticket.html.haml if !is_preview && ticket_pool.sold_out?   = "Sold out" 

But for the entire tree of partials to work correctly we still need to pass down event_pool which needs to have #pool_for_ticket_id method, even if at the end we decide not to check the availability status of returned ticket_pool.

For me it looked like a great case for applying Null Object Pattern.

class PreviewEventPool   class PreviewTicketPool     def sold_out?       false     end   end   def pool_for_ticket_id(*)     PreviewTicketPool.new   end end 
class Controller   def preview     event = current_user.events.find( params[:id] )      respond_to do |format|       format.html do         render 'events/show', locals: {           event: event,           event_pool: PreviewEventPool.new,           is_preview: true         }       end     end   end 
# show.html.haml = render 'events/tickets', {     tickets: event.tickets,     event_pool: event_pool,   } 
# events/_tickets.html.haml - tickets.each do |ticket|   = render 'events/ticket', {        ticket: ticket,       ticket_pool: event_pool.pool_for_ticket_id(ticket.id),     } 
# events/_ticket.html.haml if ticket_pool.sold_out?   = "Sold out" 

If all the places which care whether we are in a real mode or preview mode adopted this approach, bunch of if-statements could be removed in favor of using properly named classes with identical interfaces. Some would be used only when a real event is displayed, some only when the preview is shown.

The code using dedicated Null-* classes (in our case the view) wouldn’t care and wouldn’t know if this is preview or not. The logic for preview behavior would be localized in those classes.

We could also completely eliminate the is_preview variable in the end. In this case we only eliminated it for the related part of code.

Did you like the blogpost? Join our newsletter to receive more goodies.

Testing an Event Sourced application

Testing an Event Sourced application

Some time ago I’ve published a sample application showing how to build a simple event sourced application using Rails & RES. But there was a big part missing there – the tests.

My sample uses CQRS approach to handle all operations.

That means the control flow is as follow:

  • A command is created based on params from UI
  • Command is handled by a command handler:
    • based on command’s aggregate id all events for an aggregate are loaded from RES and aggregate state is recreated
    • a domain object method is called that will produce new domain events
    • domain event are applied to the aggregate
    • domain events are stored in RES & published to event handlers

AAA

This is a basic pattern how good test should be created. There are 3 parts: Arrange – when you setup initial state for a test, Act – where you perform actual operation you want to test and Assert – when you check results.

And the AAA pattern should be preserved for Event Sources application.

Given a series of events

How to build an initial state when you don’t have a state?

This should be quite easy. Any state is a derivative of domain events. You could build any state by applying domain events.

To build a state you just need some events:

include CommandHandlers::TestCase  test 'order is created' do   event_store = FakeEventStore.new   aggregate_id = SecureRandom.uuid   customer_id = 1   order_number = "123/08/2015"   arrange(event_store,     [Events::ItemAddedToBasket.create(aggregate_id, customer_id)])   # ... end  # ./test/lib/command_handlers/test_case.rb module CommandHandlers   class FakeEventStore     def initialize       @events = []       @published = []     end      attr_reader :events, :published      def publish_event(event, aggregate_id)       events << event       published << event     end      def read_all_events(aggregate_id)       events     end   end    class FakeNumberGenerator     def call       "123/08/2015"     end   end    module TestCase     # ...     def arrange(event_store, events)       event_store.events.concat(events)     end     # ...   end end 

Then we have our test state arranged. Notice that I’ve used fake event store & domain services to avoid dependencies and have really fast tests.

When a command

In Event Sourced application act (operation we want to test) is usually handling of a command. To do it you just need a command, you need the command handler and then just dispatch the command to the command handler.

test 'order is created' do   # ...   act(event_store,     Command::CreateOrder.new(order_id: aggregate_id, customer_id: customer_id))   # ... end  # ./test/lib/command_handlers/test_case.rb module CommandHandlers   # ...   module TestCase     include Command::Execute      # ...     def act(event_store, command)       execute(command, **dependencies(event_store))     end      # ...     private     def dependencies(event_store)       {         repository:           RailsEventStore::Repositories::AggregateRepository.new(event_store),         number_generator:           FakeNumberGenerator.new       }     end   end end 

The same Command::Execute module is used in ApplicationController to dispatch real commands to the system.

Expect a series or events

You should not assert on the current state, actually you should not rely on a state at all. All you need to verify is if the correct domain events have been produced.

test 'order is created' do   # ...   assert_changes(event_store,     [Events::OrderCreated.create(aggregate_id, order_number, customer_id)]) end  # ./test/lib/command_handlers/test_case.rb module CommandHandlers   # ...   module TestCase     # ...      def assert_changes(event_store, expected)       actuals = event_store.published.map(&:data)       expects = expected.map(&:data)       assert_equal(actuals, expects)     end      def assert_no_changes(event_store)       assert_empty(event_store.published)     end   end end 

And because all state is a result of events checking what have been produced has a nice side effect. You test if all expected domain events have been produced and if only the ones expected. In that case, you test if any unexpected change have not been introduced.

or an exception

Remember that any command may end up with an error. There could be various reasons, technical ones (oh no! regression again?), or error could be just a result of some business rules validations.

Complete code sample for blog post could be found here.

Am I ignored in my async team?

When we work in async teams, we have many benefits from it – people not blocked on each other, freedom of place, freedom of time. We also have some drawbacks. You can’t expect an instant reply to whatever you ask for. In the nature of async, you can’t even be sure when you get the reply. What’s interesting, you can’t even be sure that all (any?) people actually received your message.

In distributed systems we have the same problems (is the other server down?). We’re not machines, but some techniques may be worth applying. Which ones come to your mind?

In some cases, you may think that you are being ignored. That’s a bad feeling (been there). What I do in such case is that I remind myself that I also didn’t reply to every conversation that is happening. Sometimes I’m the one who ignores. It’s never intended. Often, it’s because I’m super busy and I don’t want to switch the context immediately. I try to be organized and when I see an important conversation to participate I add a task to my GTD (recently it’s Apple Reminders). It’s not always the case, though. Sometimes I fuck up and don’t remember to come back to that conversation. If there’s more people like me who don’t answer – the asking person may feel terrible and that’s sad.

I know that this may be expecting too much, but I expect the asking person to “internally sell” the conversation/question/problem in better ways. First of all, friendly-ping the topic again after some time. Consider using another medium – slack/hackpad/discourse/mumble/trello/github/email/standup.

Async teams are great but require some special skills – overcommunication, proactiveness, trust (always assume the best intentions), selling skills, good writing.

BTW, As Arkency, we add anarchy to the async environment. What does it mean in practice? You don’t need to ask for agreement on something. It’s good to overcommunicate what you’re doing and make your idea happen. In the worst case, me or someone else will jump and say – “don’t do that please” and this can start a discussion.