Icon resizing for Cordova

Both the iOS and Android platforms require multiple versions of icon sizes to be provided. If you need to change the icon at some point you have to regenerate all the icons again. This can be automated using ImageMagick which can resize and create images with the command line.

cordova-icon

cordova-icon is a simple script that takes an icon.png file from the root of your cordova project and automatically generates icons with the right sizes for all the platforms that have been added.

Install cordova icon using npm

 $ npm install cordova-icon -g

ImageMagick is required, if you’re on a Mac install it with:

$ brew install imagemagick

Create a new cordova project:

 $ cordova create hello com.example.hello HelloWorld

Go into the cordova project’s folder and add the platforms you’ll be using:

 $ cd hello
 $ cordova platform add ios
 $ cordova platform add android

Save an icon.png file to this folder (I use the iTunes icon which is 1024x1024) and run:

$ cordova-icon

All the icons will be generated for you in the right paths to replace the cordova icon placeholders.

I also add cordova-icon as a hook to the cordova-cli so every time I run the cordova build the icons are regenerated for me. When I want to update an icon I replace the icon.png file, run the build and all the icons are updated for all the platforms I have. (see instructions to set up the hook in the repo)

I hope you find it useful as well. Let me know if you have other productivity tips for working with cordova.

Configuring apache

Apache configuration should be set accordingly to the instance apache runs on. If the configuration values are too high - on a large number of requests, apache might choke by starting too many httpd processes which will increase the load average on the instance drastically and kill the server. Each one of these processes will open an sql connection, but won’t close it since it will never complete properly. You might notice a lot of open mysql connections when it happens.

When using apache with the recommended (and more popular) prefork configuration, you need to configure the following values:

StartServers - number of server processes to start

MinSpareServers - minimum number of server processes which are kept spare

MaxSpareServers - maximum number of server processes which are kept spare

MaxClients - maximum number of server processes allowed to start

MaxRequestsPerChild - maximum number of requests a server process serves

The value for MaxClients should be set according to the value of the available RAM:

available RAM / RAM per httpd process

To check RAM on your server, run the following command:

egrep --color 'Mem|Cache|Swap' /proc/meminfo

RAM on an aws medium instance is ~3.6GB

To determine the optimal values, try to test the server under high load and run the top command and examine the load average.

To edit any one of these values from the command line you can use:

sed -i 's/StartServers          16/StartServers          12/g' /etc/httpd/conf/httpd.conf

don’t forget to restart apache for the changes to take effect

apachectl restart

(NOTE: if you’re using AWS OpsWorks to setup apache, the default template configures apache for a large ec2 instance, so you must adjust httpd.conf if you’re running a smaller instance)

Randomizing bot execution with randomizer

If you’re building a bot and would like a quick way to add some randomness to make it look less like a bot, check out the Randomizer library. Randomizer let’s you randomly decide when to execute a command based on a given probability.

For example, execute a command 3 out of 7 times:

var randomizer = new Randomizer();
randomizer.every(3).outOf(7).times.execute(function () {
  console.log('executing!');
});

You can also make it execute only during day time (your bot has to sleep no?)

randomizer.ifItsDayTime.every(3).outOf(7).times.execute(function () {
  console.log('executing!');
});

You can configure what is considered day time first:

Randomizer.defineDayTime({
  'from' : 6,
  'to'   : 22,
});
randomizer.ifItsNightTime.every(1).outOf(4).times.execute(function () {
  console.log('executing!');
});

Setting up remote logging to papertrail using chef

One of the options to send logs to papertrail on a unix system is to use the syslog. When using chef for provisioning, the following ruby code will modify the syslog configuration file but only if it was not already modified before:

PORT = 12345 # make sure to replace with your account's port
execute "echo \"*.*          @logs.papertrailapp.com:PORT\" >> /etc/rsyslog.conf" do
  not_if "grep -q papertrail /etc/rsyslog.conf"
end
execute "/etc/init.d/rsyslog restart"

or if you’re using bash scripts for provisioning:

if grep -q papertrail /etc/rsyslog.conf; then
  echo "papertrail already installed"
else
  echo "installing papertrail"
  echo "*.*          @logs.papertrailapp.com:12170" | sudo tee -a /etc/rsyslog.conf
fi

to quickly test the logging by writing to the log:

logger testing connection

Logging resque with monolog

PHP-Resque is a php library for creating workers that will execute background jobs using a redis queue. It is a port of the Resque Ruby library developed by Github and stores the data on redis using the exact same data format. The library is logging to STDOUT and has the “VERBOSE” and “VVERBOSE” settings to choose between basic and detailed information. There is also an event/hook system that allows for a more custom logging solution.

The PHP-Resque-Log library is a plugin for resque to log the workers execution using the Monolog library. Monolog supports different loggers and provides an easy way to switch between loggers.

Using php-resque-log is very simple, an “init” function needs to be called with the logger passed as a parameter.

ResqueLog\Plugin::init([
  'logger'         => $log,
  'vverbose'       => true,
  'queueSizeLimit' => 100,
]);

An event will be logged when:

  • a new worker starts
  • a job is added to the queue, prepared for execution and successfully performed or when a job throws an exception
  • a fork is about to be created for a job and when one is created

The plugin will also monitor the queue size and log a warning when it is greater than a defined max value queueSizeLimit

Cron tasks on load balanced identical web servers

A common setup for web applications is multiple identical web servers behind a load balancer. The benefit of having such a setup is horizontal scaling. When all the web servers are exactly the same, there is no single point of failure. If there is an issue with any one of the servers, the problematic server can be quickly replaced with a new healthy instance.

A challenge that comes up with this setup is the cron configuration. Since all the servers are identical, the same cron task will execute from multiple machines at the same time when we only want it to execute once.

One possible solution is to configure only one server to execute the cron. This solution however makes one of the servers different from the others and increases the risk that this server will take down the entire application with it.

A better solution would be to use an application-wide central lock. The lock is created using redis and shared by all the web servers.

When it’s time to execute the cron, the server that will be the fastest by a fraction of a millisecond will create a temporary lock using redis and then execute the cron job. All the following servers will see that the lock already exists and exit immediately.

The “setnx” command creates a key if it does not already exist and returns 1 if a key was set and 0 if it was not. We will use this command to check if a lock was already created and create it if not.
The “expire” command sets a timeout on a key. After the timeout has expired, the key will automatically be deleted. We will use this command to set the lock to expire after a short period of time.

MutexLock is a php library that implements this solution.

Setting up the library:

MutexLock\lock::init([
    // monolog logger:
    'logger' => $log,
    // redis connection:
    'host'   => '127.0.0.1',
    'port'   => '6379',
]);

Then we check if the lock was created and create it if it wasn’t. If the lock was already created, the set function will return true and we’ll exit.

if (!MutexLock\Lock::set(LOCK_KEY, LOCK_TIME)) {
    return;
}

Welcome to my blog

I’ve started this blog to share stuff that I learn aobut mobile and web development. I will be writing mostly about devops, nodejs and frontend javascript, php, objective c, and best practices in general.