Orange is my favorite color

RedHat cycling socksJoseph Lamoree has been building a Paypal gateway for CFPAYMENT lately. He’s documenting the process and even built a sweet UML-ish diagram of how the library is pieced together. Although I’m not a Paypal user myself, this is the #1 gateway request so I’m excited to see support, especially contributed from a user. Joseph and I met at cf.Objective() a little over a month ago when he gave me these sweet cycling socks. Thanks for all of the contributions!

I shy away from database replication because it tends to require a lot of monkeying around with complex systems to get it working right. Postgres has a simple log shipping feature but you can’t query the warm standby while other replication tools give you all kinds of option for synchronous vs. asynchronous and multi-master, master-slave, etc.

Enter RubyRep, a Ruby-based replicator that already supports both Postgres and MySQL and has plans to also support Microsoft SQL Server, Oracle and IBM. The author has published a screencast where he enables and demonstrates working replication in less than 5 minutes.

It handles composite primary keys, single primary keys, sequences/uniqueids and even tables without primary keys with a touch of configuration. It works using triggers which it installs and maintains automatically. There are some limitations with MySQL since it only supports one trigger per table which could collide with an existing application trigger. We’ll have to see what performance is like but it’s pretty compelling so far.

Postgres 8.4 RC1 is out too - might be a good opportunity to roll out a test environment and start playing.

I’ve been getting up to speed with Luis Majano and Mark Mandel’s ColdFusion-based Codex Wiki. My use case is a little different from some of the existing installations like docs.transfer-orm.com where the wiki is the site. Instead, I want to embed Codex as a knowledge base and help repository inside of my existing Model-Glue application. I’m a total ColdBox neophyte so I am sharing this guide in case anyone wants to do something similar.

Incorporating Codex as part of your code

My preferred method for including a third-party code base is to use Subversion’s svn:externals. Specifically I have been using a “local external” repository which gives me the benefits of svn:external without the deploy-time dependency on a remote repository that may not be available.

Thus, in my application, I have an svn:external that points like so:

http://myrepo/externals/codex/tags/trunk_r298 help

Where the codex/tags/trunk_r298 folder is simply a copy of the Codex trunk at revision 298. When I run svn update on my application, it extracts the Codex codebase into a /help directory. All’s great right? If you don’t want to modify the look and feel, then you’re done.

The problem with modifying Codex

Most people however are going to want to customize the layout and CSS at a minimum so you’ll need to modify the layout and view CFM files. That’s pretty straightforward but what happens when Codex releases an update? And what about the configuration file - where will you put that? What a train wreck - now you need to merge your files into theirs and hope there are no conflicts.

To embed Codex (or really any ColdBox application) into your app, you’ll need to adjust three things:

  1. Move the coldbox.xml.cfm file to a location outside of the Codex tree
  2. Relocate the view files
  3. Relocate the layout files

A Better Way

This may be common knowledge to Coldbox developers but I stumbled upon it through trial and error. There is a way to externalize your configuration and your views such that your external views only serve as an override rather than the default. This lets you take advantage of updates that come from the Codex team while keeping your modification footprint as small as possible. Let’s start with a partial directory tree where Codex has been checked out into the /help directory and my Model-Glue application has its own /views directory structure:

/
+ gfx
+ help (this is Codex, checked out via svn:external)
    + config
    + handlers
    + ...
    + layouts
    + model
    + plugins
    + views
    Application.cfc
+ controllers
+ views
    + help
         + views
             + tags
             footer.cfm
             header.cfm
             ...
         + layouts
             Layout.html.cfm
             Layout.Main.cfm
             ...
Application.cfc
index.cfm 

Each ColdBox application has a configuration section called “Conventions” that are optional adjustments to the defaults. The general strategy is to turn Codex back on itself by making it look for the default in your external folder and then look for the override in the standard Codex folder. In this manner, if you have a file in your own views folder then it will be used, if not, it will go searching for the default file under the Codex directory tree. You’ll need to add this section to your Codex config file:

<Conventions>
	<layoutsLocation>../views/help/layouts</layoutsLocation>
	<viewsLocation>../views/help/views</viewsLocation>
</Conventions>

Conventions will work with a relative path so I am pointing my default views to be in my Model-Glue views folder instead of the Codex directory. Codex (or more specifically, Coldbox) will first look in my /views/help/* directories instead of /help/layouts and /help/views.

Perfect! Now my layout and views are external so I can manage them independently of Codex upgrades. But, what if I only want to make small changes, like put my logo in the header? It would be a bummer to manage all of those files for such a simple change! Thankfully Coldbox has a Setting called ViewsExternalLocation:

<Setting name="ViewsExternalLocation" value="views" />

Put alongside the other Settings in your configuration file, this tells Codex to override any default views with those found in the standard Codex views directory. At the time of this writing with Coldbox 2.6, there is no corresponding LayoutsExternalLocation but Luis Majano said it would be coming in 3.0. In the mean time, you will need to include all of the 5 or 6 layout files in your custom layout folder but you only need to include the views you wish to override or add.

You can verify this works by creating a single file like (using my directory structure) /views/help/views/wiki/show.cfm (which is used to display a wiki page) and adding some extra text to it. Reinitialize Codex, view a wiki page and you should see your changes.

Moving the Configuration File

Since Coldbox is all about conventions, you must override the default to point at a configuration file in a different location and this will take some editing. This is one place where you will need to make one small change each time you update Codex or script it for your deployment using something like Ant. Automating your deployment is a good idea if you’re not already doing it.

The /help/Application.cfc defines where the configuration file lives. Each time you update Codex (either via svn:external or unzipping of a file), you’ll need to modify a single line like so (or, see the Coldbox docs):

<cfset COLDBOX_CONFIG_FILE = "../myconfig/codex.xml.cfm">

In this case, I’m using an example directory of /myconfig with a copy of the configuration file that I renamed from coldbox.xml.cfm to codex.xml.cfm. Move your file, save the Application.cfc and reinitialize and you’ll now be running off the XML file managed by your own version control rather than the one provided in the standard Codex distribution.

That’s it, you’re ready to modify the look, feel and configuration of your Codex wiki (or really any other ColdBox app) without resorting to modifying the actual distribution. This will make future upgrades much easier and less fragile which will encourage you to do them more frequently.

Bonus Tip for Automating Application.cfc Edit

If you’re using Ant, you can automate the replacement of the Application.cfc file on every deployment using the following task:

<replace file="/help/Application.cfc">
	<replacefilter token="<cfset COLDBOX_CONFIG_FILE = \"\">" value="<cfset COLDBOX_CONFIG_FILE = \"../myconfig/codex.xml.cfm\">" />
</replace>

Now you can update with impunity and your Ant script will automatically fix the configuration file pointer during deployment.

Are you thinking about moving to Amazon’s EC2 service? But you get to the part where you’re calculating how much your persistent (EBS) storage will cost and you have no idea? The Amazon pricing page looks like this:

Amazon EBS Volumes

  • $0.10 per GB-month of provisioned storage
  • $0.10 per 1 million I/O requests

Well, I’d like to know how much it’s going to cost to run my database before I move it over and I can’t find squat on the Intarweb on how to estimate this cost. But assuming you’re running Linux, there is an easy way by looking at /proc/diskstats:

[brian@db2 ~]$ cat /proc/diskstats
 104    0 cciss/c0d0 5946064 12358605 1783920022 267694420 26411136 296537705 2583591570 34712288540 53639757 3738914277
 104    1 cciss/c0d0p1 553 2156 2 10
 104    2 cciss/c0d0p2 194565 1556520 192647 1541176
 104    3 cciss/c0d0p3 18109735 1782360706 322755967 2582047424
 104   16 cciss/c0d1 6579320 1005537 566670186 27193242 13685423 33336126 376172656 26751430 023642414 53937189
 104   17 cciss/c0d1p1 7584779 566669554 47021570 376172552

This is a device with hardware RAID so we want to ignore the individual partitions (c0d1p* for example) and look at the disks c0d0 and c0d1:

cciss/c0d0 5946064 12358605 1783920022 267694420 26411136 296537705 2583591570 34712288540 53639757 3738914277
cciss/c0d1 6579320 1005537 566670186 27193242 13685423 33336126 376172656 26751430 0 23642414 53937189

According to these directions on reading the numbers, you can add the first and fifth numbers of that row to get total reads and writes respectively since the system was started. To calculate your total I/O requests per month (what Amazon will charge you), just plug your numbers into this formula:

Cost = $0.10 * 30 days * ((first number) + (fifth number)) / (days of uptime)

You can get this number another way by using iostat as well which will give you the average number of transactions per second since boot:

Device:            tps   Blk_read/s   Blk_wrtn/s   Blk_read   Blk_wrtn
cciss/c0d0        1.56        86.17       124.80 1783920022 2583601386
cciss/c0d1        0.98        27.37        18.17  566670378  376184592

If you take the average TPS for your disks and multiply them out, you get roughly the same number (good enough to make a cost estimate for EC2):

Cost = (TPS of all disks) * 60s * 60m * 24h * 30d

You can see this particular box is under very light load with only 6,583,680 I/O requests per month. With EBS that would cost about $0.65. I think we can afford that. :)