Code

This portion of the site is devoted to software code and other topics of interest for a software engineer.

My First Bottle Stopper On Etsy

Categories: Code, Wood

Posted:

I’m testing the waters with selling my bottle stoppers on Etsy. The site has the benefit of an existing user base, but my small collection of items (currently only one) is most likely lost among the vast quantities of items. I posted a cherry bottle stopper with a stainless steel base as my first test. There has been almost negligible traffic to the item listing with almost every page hit being sourced from the bit.ly link that I’ve posted in a few places. I plan on posting a few more bottle stoppers up there to site for a while. From what I’ve learned so far, popular stores are somewhat self sustaining, but newer, smaller sellers are all but lost in the void. The $0.20 posting fee is trivial and spending a few dollars to force myself to think about how I can market my woodworking crafts is a worthwhile expense.

An alternative to selling on Etsy is to host my own store. OpenCart is currently in the lead of the free apps. Magento was quickly eliminated as being too large/complicated for a site that would only have a few dozen items for sale. I also couldn’t image being able to turn a client loose on its admin interface to manage their business.

Related to the self hosting, I still have a few shared accounts with Joyent. The uptime has been great and my only complaint is that I didn’t upgrade my lifetime shared hosting when they started offering accelerators. That would have given me more options and capabilities with the hosting. In search of a cheap VPS hosting option, I found LowEndBox.com, a blog that posts sub $7/mo hosting deals. If you set your expectations appropriately and do a little bit of research about the companies providing the offer, then you can find a good deal. I managed to get a dedicated 2gb OpenVZ from ChicagoVPS for $7/mo. For the price, it is exceeding my expectations and I plan on hosting a few personal sites and services that can tolerate some downtime. There hasn’t been any provider caused downtime yet, but my expectations are not set to a level I would need for a production site. My expectations may change with time.

ImportError: No module named os

Category: Code

Posted:

When running Python 2.7 with Apache 2.2 and modwsgi 3.3. Make sure Apache is loading the correct version of modwsgi. I ran in to the following error, which wasted about 15 minutes of my life before realizing the one character typo.


[client 192.168.0.10] mod_wsgi (pid=5800): Exception occurred processing WSGI script 'D:/www/myapp.wsgi'.
Traceback (most recent call last):
  File "D:/www/myapp.wsgi", line 1, in <module>
  ImportError: No module named os

That puzzling error was the result of the following line in the httpd.conf.

LoadModule wsgi_module "@WWWROOT@/modules/mod_wsgi-win32-ap22py26-3.3.so"

See it? The line should be.

LoadModule wsgi_module "@WWWROOT@/modules/mod_wsgi-win32-ap22py27-3.3.so"

Running Python With Apache on Windows

Category: Code

Posted:

My day job has a Windows environment and avoids installing other OSes unless absolutely necessary. Windows is great on the desktop, but has many limitations when tasked with running a web site that relies heavily upon open source languages and products. Its limitations are front and center when trying to host a Python web application. Below are some of the gotchas that I’ve encountered and how I addressed the problem.

The Python GIL

Every Python developer should be familiar with the GIL. If you’re not, follow that link and start reading. TL;DR? Threads of the same process block each other on all IO. By itself, the GIL is an easy beast to tame by spawning more processes, instead of threads. On *nix OSes, processes are relatively light weight and you can fork a process and continue on your merry way. Processes on Windows are heavier and it does not support fork without installing more software. Cygwin and Windows Services for Unix are the two ways of making Windows behave more like *nix for specially compiled programs.

Apache MPM (Multi-Processing Modules)

Apache is a great HTTP server application that provides more functionality than most sites will ever need or use. It is also one of the few options that is designed to run as a service on Windows. The lighter weight options, nginx and lighttpd are usually better for my needs, but both have issues with running as a Windows service.

Apache supports a few different Multi-Processing Modules, prefork is the default for *nix. On Windows, there is only one MPM, mpm_winnt. This MPM works great and follows the Windows idea of spawning threads when you want work done. The GIL makes almost any Python website unusably slow when run on Windows with Apache. Most web applications are a bunch of IO (Network, database, disk, etc.) with a small amount of CPU. This basically turns Apache in to a single threaded web server. The prefork MPM does not experience this problem due to its use of processes instead of threads.

I observed the situation where a page that by itself would take about 1 second to generate, could take tens of seconds to finish if there were more than 2-3 overlapping requests. Each new request (in a thread) would get roughly equal time and slow down all previous threads. It was possible to block the site for minutes with as few as 10 requests.

Faking a Python MPM

There is a way of configuring a Windows server so that it can serve a Python web application and avoid the GIL. A multi-process MPM is conceptual the same as a load balancer sitting in front of several web servers. An incoming request is routed to a individual web server to handle.

Apache as a Balancer

Apache can function as a load balancer if another option is not available. Here’s a configuration snippet that will equally balance requests among three Apache instances running on the same machine as the instance acting as the load balancer (reverse proxy). See mod_proxy documentation for the rest of the configuration directives that you will need to fully configure.

<Proxy balancer://cluster>
	BalancerMember http://192.168.0.10:9001 smax=3 max=10 ttl=120 route=www_1
	BalancerMember http://192.168.0.10:9002 smax=3 max=10 ttl=120 route=www_2
	BalancerMember http://192.168.0.10:9003 smax=3 max=10 ttl=120 route=www_3
</Proxy>

ProxyPass / balancer://cluster/ ProxyPassReverse / balancer://cluster/

Gotchas

This configuration of faking a server farm on a single machine requires some new problems to be resolved. Thankfully, these are not that difficult once you are aware of them.

Lots-O-Logs

Every request will be logged by the load balancing Apache instance and the proxied instance that does the work. This is not necessarily a bad thing by itself. It is useful to know which Apache instance handled a specific request and also get the aggregate view (load balancer logs). Unless steps are taken, this will double the disk IO and space requirements.

The simple resolution is to disable all logging on the worker instances. This can be accomplished by using CustomLog and a conditional environment variable that is never set.

LogFormat " " empty
# Below will never output anything, but it will create an empty file
CustomLog "D:/logs/carme/apache/access-1.log" empty env=NOTHING_IS_LOGGED

Logging has now been reduced to a normal volume, but you will not know which instance handled the request. To regain that bit of information, you can add %{BALANCER_WORKER_ROUTE}e to the LogFormat of the load balancer. This will include whatever value is set for route= in the above BalancerMember configuration. E.g. www_1, www_2, or www_3.

Fixing IPs

The instances behind the load balancer, and application code will see every request as if it is coming from the load balancing instance. This can be resolved with the Apache module mod_rpaf.

Auto-enabling Textpattern Plugins

Categories: Code, Projects

Posted:

Upload plugin. View the code and help. Scroll. Click “submit”. Scroll. Click “No” to enable plugin. I’ve repeated this pattern way to often whenever I set up or update a Textpattern based site. No more.

Textpattern added the ability for plugins to run some code when they are installed; PLUGIN_LIFECYCLE_NOTIFY. This was intended to let a plugin update database schemas, create default forms, or do any of the other set up work the plugin needs to only do once.

Going forward, I plan on updating all of my plugins to enable themselves when installed. My first public plugin to gain this benefit is mem_self_register v0.9.9.

Release Notes:

  • added ability to customize new password reset mail message.
  • auto-enabled on install.
  • numerous fixes related to creating email messages.

How to auto-enable a plugin

Set the plugin[‘flag’].

$plugin['flags'] = PLUGIN_LIFECYCLE_NOTIFY;

Register the callback function.

if (@txpinterface == 'admin')
{
	register_callback('mem_self_auto_enable', 'plugin_lifecycle.mem_self_register', 'installed');
}

Provide the function that sets the status of the plugin in the database.

/** Automatically enable plugin when installed */
function mem_self_auto_enable($event, $step)
{
	$plugin = substr($event, strlen('plugin_lifecycle.'));
	$prefix = 'mem_self_register';
	if (strncmp($plugin, $prefix, strlen($prefix)) == 0)
	{
		safe_update('txp_plugin', "status = 1", "name = '" . doSlash($plugin) . "'");
	}
}

Facebook Decrapifier

Categories: Code, Projects

Posted:

No big surprise, I’m not a fan of the most recent changes to Facebooks UI. I’m sure they spent hundreds of person hours discussing, designing and implementing the latest changes, but it only took me 5 minutes with a grease monkey script to remove the worst bits of it. I present to you, the Facebook Decrapifier. This script will hide the “byline”, random images and ads from all user profiles.

facebook decrapifier

To use this script, you will need to install the Grease Monkey (firefox) extension and then click this link. I haven’t tested this with any of the grease monkey clones for other browsers, but they should work.

« Newer - Older »

Code Repositories