Half-Elf on Tech

Thoughts From a Professional Lesbian

Author: Ipstenu (Mika Epstein)

  • How Do You Solve a DB Like Maria?

    How Do You Solve a DB Like Maria?

    I was talking to my friend James about upgrading SQL. If you didn’t know, upgrading SQL is a horrifyingly monumental thing, because there’s no way back except restore from a backup. Minor upgrades are generally painless, but the CentOS warning is as follows:

    Upgrades to new major releases (the first two digits in the version string) are more involved because there is a substantial risk of data loss.

    Data. Loss.

    It’s scary when you consider doing it for yourself. It’s horrifying when you consider doing it for a few thousand users.

    On top of that is the issue that MySQL is owned by Oracle and they’re not exactly known for being good stewards of OpenSource. Unlike many other Open Source projects, Oracle owns the entire copyright to MySQL. All contributions are done if the developer has signed a “contributor agreement” that assigns ownership to Oracle. This isn’t all that weird, to be fair. When I worked for The Man, that was basically how things worked and it made sense. The work I did for the company belonged to the company.

    Where this is weird is that Oracle has said that about a GPL product, even to parts of it the company has not written. Why is that? It’s because all contributors to the code have to sign a “contributor agreement” assigning ownership of the copyright to Oracle, which is not alone in this. Sun before them used contributor agreements to get full source ownership, and many other projects do the same.

    Now, James and I looked at the MariaDB vs MySQL compatibility doc and had a laugh.

    tl;dr “For all practical purposes, MariaDB is a binary drop in replacement of the same MySQL version,” except for this long list detailing where you’re screwed.

    Now when you get down to MySQL 5.5 and MariaDB 10, the issues become very minor and unlikely to cause you migraines, which is a relief, but that list sure is long and daunting.

    I’m not yet running MariaDB because it’s an all-or-nothing move. I can’t keep on MySQL, and I have a few old (ancient) bits of non-WordPress code on this server. I always stress that WordPress is not the limiting factors in server upgrades, and it’s still the truth.

    I’ve started doing the recon work to make sure MariaDB will work for all situations on my server, for all apps, and I’m currently pretty sure that I’ll be fine, but I do have one way-out-there app to check into. They’re also one of the few people who pay me for hosting, so we may have to have a sit-down anyway to discuss their future.

    The most important question has been answered.

  • Git Flow

    Git Flow

    Late as always to these git things.

    In the ever increasing madness to the method of making code easier to do, we come to the automation of git-flow. This is a library of git subcommands that helps automate some parts of the flow to make working with it a lot easier if you’re using Vincent Driessen’s model.

    This model is not bad, if a little confusing at first:

    The git-flow model

    Jeff Kreeftmeijer already has a good primer for it so these are just my quick notes to add in things that should have been obvious. The basic concept for the model is that you have two main branches, master (the ‘current’ version) and develop (where you’re working on the next version).

    Install git-flow

    You have to install it to use it. I use Homebrew so it was brew install git-flow and that was that.

    Add it to your repo

    Again, you have to add it to have it. git flow init is run inside the repo and you’re good, except you may not be.

    Since I’m starting from an existing repository, which was up to date in master, I made a new branch: git checkout -b develop

    Then I ran git flow init which is not the same as it would be on a new repo:

    $ git flow init
    Which branch should be used for bringing forth production releases?
       - REL_3.3
       - REL_3.3.1
       - REL_3.3.2
       - master
    Branch name for production releases: [master] master
    
    Which branch should be used for integration of the "next release"?
       - REL_3.3
       - REL_3.3.1
       - REL_3.3.2
    Branch name for "next release" development: [master] develop
    
    How to name your supporting branch prefixes?
    Feature branches? [feature/]
    Release branches? [release/]
    Hotfix branches? [hotfix/]
    Support branches? [support/]
    Version tag prefix? [] REL_
    

    Should you happen to do as everyone says and ‘accept the defaults’ you get this:

    Branch name for "next release" development: [master]
    Production and integration branches should differ.
    

    Also if you don’t have a develop branch, it punts you out.

    Branch name for "next release" development: [master] develop
    Local branch 'develop' does not exist.
    

    So a couple ooops along the way. It’s not

    Using A Feature

    First you make a feature:

    $ git flow feature start utility_1.0.3
    Switched to a new branch 'feature/utility_1.0.3'
    
    Summary of actions:
    - A new branch 'feature/utility_1.0.3' was created, based on 'develop'
    - You are now on branch 'feature/utility_1.0.3'
    
    Now, start committing on your feature. When done, use:
    
         git flow feature finish utility_1.0.3
    

    Eventually you’ll be done and use that finish command, which merges it all back into ‘develop’ and changes you back to that branch. Which is good for reasons we get to in a moment. Since I work on multiple computers, I do this at the end of my workday:

    $ git push --all
    Total 0 (delta 0), reused 0 (delta 0)
    To ipstenu@example.com:/home/ipstenu/repositories/theme-wordpress.git
     * [new branch]      develop -> develop
     * [new branch]      feature/utility_1.0.3 -> feature/utility_1.0.3
    

    So now when I do my pull later on the other computer, it’ll be easily usable. Provided I remember to install git-flow and init it on my other laptop. But it’s a little more complicated than just that.

    Releasing a Release

    You can only run this from the develop branch, which makes the previous command pretty awesome, right? So now we’ll do this: git flow release start RELEASE

    Once we’re good to go, it’s git flow release finish RELEASE

    What About Two People?

    This is where we want to use publishing. Technically I’m collaborating with myself across two computers, so I always publish my feature to my remote server so it can be used by my other self: git flow feature publish MYFEATURE

    To pull the feature down, git flow feature pull origin MYFEATURE is just as logical. And that’s actually how I handled pulling the feature utility_1.0.3 onto my work laptop.

    $ git checkout master
    Switched to branch 'master'
    Your branch is up-to-date with 'origin/master'.
    $ git branch develop
    $ git flow init
    [snip .. same as before]
    $ git flow feature pull origin utility_1.0.3
    Created local branch feature/utility_1.0.3 based on origin's feature/utility_1.0.3.
    

    There’s a good cheat sheet for help about this called Git Flow Cheatsheet.

    Now there’s nothing but to do it.

  • Mailbag: Facebook Page Notifications

    Mailbag: Facebook Page Notifications

    A family member, after teasing me for not knowing someone was married because the only place they announced was on Facebook (and Shredder? You’re not off the hook either), finally asked:

    Why do you still hate facebook?

    Because the interface is inconsistent and sucks. Let me explain by showing you about my Page Notifications.

    I still use Facebook under duress and happily go weeks without noticing I have alerts waiting. When I do remember to check in, this is usually my first clue I have that there are unread notifications:

    Sidebar alert - a VERY subtle count

    If I click on the group, the toolbar at the top of the page gives me a much better idea of what’s going on:

    Page Navigation bar lists how many unread I have

    So I logically click and I get this:

    The notification page has the number on the left and a non-distinct way to see what's unread on the right

    I don’t like that I have to click three times just to see my notifications. Yes, I can click on that teeny-tiny number to go to the page properly and wipe them, but what if I don’t want to? Also have you noticed how small the number is? It’s hard to hit if you’re not ‘great’ with your mouse. Guess what I’m not? Great with my mouse. I like larger icons because they’re easier for me to tap. I’m not the only one.

    The next problem is the text color. It’s not really all that distinct. It changes to a useful red/orange on other pages, but the subtle grey on blue grey, combined with the size, makes it weird. Compare it to the alerts you get for unread posts in your timestream, or personal notifications:

    The top bar says I have 1 new friend request and 13 posts that I should read

    Clearly their goal is to keep me on that front page (which is obviously why they swap my ‘recent posts’ to ‘top posts’ every chance they get). But even then, once you click on the item, the number goes away but the items are not marked as read. You still have the mark-as-read buttons, which are not very noticeable or distinct. In the case of a page, the number count on the sidebar goes away, but not the one on your toolbar or the notifications page. Welcome aboard the inconsistency train, thy name is Facebook.

    Interestingly, this day when I clicked on the “Mark as Read” link, the number dropped from 20 to 1. But there was nothing else to mark as read. All the backgrounds went from pale blue to white, and there was no other indication as to how I might find what was unread.

    Eventually I saw the sidebar:

    Sidebar lists ONE unread notification

    There it was. I hovered over it, clicked ‘Mark As Read’ and that number went away. I had to refresh the page to make the orange alert go away, because apparently that level of Ajax is hard.

    My conclusion is pretty simple. Facebook wants me on the main page of their site, my timeline, all the time, and that’s fine for a user. But in doing so, they’ve made administration of their pages and groups overly complex and inconsistent with the rest of the flow of their site. They want me to add in content, but they’re going to decide how I, and others, consume it, which means my ability to easily input and manage is secondary (or even tertiary) to their consumer design.

    The pages and groups are a nice idea, but still ill planned for a ‘MySpace’ replacement. The only reason that even worked was because MySpace blew up on itself.

  • Defines, Variables, and Plugin Dirs

    Defines, Variables, and Plugin Dirs

    If you’ve spent any time looking at PHP code, then you’ve seen defines and variables

    Defines

    A define looks like this:

    define('SOMETHING', true);
    

    This makes a global constant that can be used anywhere. In the case of WordPress, it means they can be used across multiple plugins or themes. This is very useful if you make a suite of plugins that all have the possibility of using the same API key. Then you can tell a user to put define('MY_PLUGIN_API', '123456'); in their wp-config.php file, and tell your code to check for the define.

    A define also cannot be redefined. If you call it twice, you get errors, so you should be as unique as possible when creating yours.

    Variables

    A variable, meanwhile, looks like this:

    $SOMETHING = true;
    

    Variables only exist where they are, so if I have one in one function, I may not be able to call it in another. You can make global variables if needed, and in fact if you don’t, the variable won’t be available to all functions.

    Which Should I Use?

    Keeping in mind that defines are constants and variables are, well, variables, the idea is that a constant should be used for things that should not change in the running of the code. It also makes your code easier to maintain if the things that must be constant are explicitly so.

    So what’s a good define? Actually not really this:

    define('MY_PLUGIN_VERSION', '1.0');
    

    This is a constant, it’s something you should be setting and it shouldn’t be overwritten, but actually I’d want to make it a database field to check on before upgrading. Remember, you should be changing that define on upgrade, so having it be a declared constant is a little odd. Now that said, it is a good one when you consider you don’t want someone to willy-nilly override it. Except … what if you do? What if you want someone to be able to change it back to re-run an upgrade?

    So then really not this either:

    define( 'MY_PLUGIN_PATH', plugin_dir_path( __FILE__ ) );
    define( 'MY_PLUGIN_URL', plugin_dir_url( __FILE__ ) );
    include( MY_PLUGIN_PATH . 'lib/asset.php') ;
    

    Someone’s probably thinking that their plugin directory is a constant and, thus, should be defined like that. Maybe, but it’s a pointless define in WordPress. You already have plugins_url() (which this example isn’t using) but it’s really where people use that code that makes no sense. That’s why I included the second line there. That’s what they use it for, and it means two lines of code for one function call.

    This actually magically becomes a good define when you have a complex plugin with multiple files and you need to grab the main plugin directory in sub-files. But if your plugin is one file (and yes, that’s where I see it the most), it’s overkill.

    This is a good define:

    define('MY_PLUGIN_APIKEY', '123456');
    

    But that should never be in your code itself. Not for WordPress at least. That should be in the wp-config.php, like I mentioned before.

    Basically … there aren’t great reasons to use defines unless you want things that never change. define('MY_PLUGIN_SUPPORT_HOME','http://help.example.com'); would make sense to me, as would other contact info you want to make sure is never subverted.

    What do you think define is best for?

    I’m interested to hear what you guys like to use defines for. I’m certainly guilty of using them for some pretty silly reason.

  • March into CloudFlare

    March into CloudFlare

    “Eating your own dogfood” is a colloquialism that describes a company using its own products or services for its internal operations. Microsoft supposedly invented it in the 1980s.

    DreamHost is partners with CloudFlare. I’ve tried time and again but I get hung up when we start talking about the delay in caching and the proxying of caches. Still, I know me. I can do things better and provide better support if I use a thing. I’m so good with PageSpeed and wp-cli now because I use them regularly.

    So it was time to knuckle down and use it for more than just a week. I was committing to a month on CloudFlare!

    Pick One Domain

    I decided to only do this for one domain. My busiest, and not a multisite, because I wanted to create a ‘real user experience.’ I didn’t use my company account. I made a new CloudFlare account, added this domain, and started there. I didn’t want Multisite because that’s where my store is, and if I screw up the busy site, I don’t lose money or risk people’s information. While I’m sure it can be used safely, I knew I was going to experiment a little, so I wanted to protect myself and them

    Turn on CloudFlare, Turn off PageSpeed

    You heard me. I turned PageSpeed off for the domain I’m testing on. I love PageSpeed, but after talking to some people, I’ve been wondering about how well it handles things. Also with SPDY and HTTP/2, compressing HTML is less and less of a concern. I wasn’t sure if there was a benefit to having everything be filtered and compressed before it loaded. Was I making the experience worse? After making sure I still had mod_cloudflare active and up to date, I used .htaccess to turn off PageSpeed.

    Break Your Code Flow

    I need to point out that CloudFlare warns you about this one. They tell you that if you need to SSH, you should use a different record or the IP. That wasn’t a big deal. I’d kept ftp.example.com separate for FTP anyway. All I had to do was change my SSH aliases to point there as well.

    I forgot that I use Git on my own server. I wanted to update a script and Coda hung. It took my brain a moment to remember that I was using Git with SSH so I had to remember how to change the remotes on Git:

    $ git remote -v
    # origin  me@example.com:USERNAME/REPOSITORY.git (fetch)
    # origin  me@example.com:USERNAME/REPOSITORY.git (push)
    

    This was a problem. My example.com main domain hit CloudFlare. So I had to change that to use ftp.example.com as well. That wasn’t too hard, just running this 6 times.

     $ git remote set-url origin me@ftp.example.com:USERNAME/REPOSITORY.git
     $ git remote -v
     # origin  me@ftp.example.com:USERNAME/REPOSITORY.git (fetch)
     # origin  me@ftp.example.com:USERNAME/REPOSITORY.git (push)
    

    Still, I felt pretty silly!

    Break Your Email

    Same song, second verse. I had to add in a CNAME for smtp.exmaple.com on CloudFlare because I use that to send emails and I use mail.example.com to receive. By default they know mail should be ignored. The scan didn’t pick up smtp. I forgot about it until I tried to reply to an email.

    Break Your Tools

    Not the ones on my computer. My other CMSs broke. CloudFlare is used to WordPress, and has Five Easy First Steps to using WordPress and CloudFlare.

    In that document, they specify this:

    Create a Page Rule to exclude the wp-admin or wp-login sections from CloudFlare’s caching and performance features. You can access PageRules in your CloudFlare ‘Settings’ options.

    e.g.

    *example.com/wp-admin/*
    *example.com/wp-login/*
    

    Why do this?

    While there is not always an issue, we have seen instances where optional performance features like Rocket Loader may inadvertently break certain functions (editors, etc.) in your WordPress back end.

    Except there are major problems (besides the fact that the second example should be *example.com/wp-login* without the trailing slash)! The free version only gives you three rules. I’m using four apps (WordPress, ZenPhoto20, Yourls, and MediaWiki). That means if I need to white list all of them, I’m out of luck.

    Then there’s the problem that *.example.com matches blog.example.com and www.example.com but does not match example.com and guess what? I’m using example.com without the WWW. I hate WWW. And yes, you can use a naked domain with CloudFlare.

    Break The Site (For One Person)

    Someone pinged me to let me know the site was down in Scotland:

    Website is Offline Message from CloudFlare

    It wasn’t in Manchester or Dublin. It wasn’t in the US. It wasn’t in Canada. I opened a support ticket after making sure that it wasn’t really me. The server was up (all other sites, including this one were up) and I could get the site via anonymous proxies. Only that user had an issue, and I was 100% positive I had whitelisted everything in CSF (it’s the same thing I do for Jetpack). But the website claims a 522 is my server.

    This was never resolved, and demonstrates a major issue in the process. The user was a non-web savvy user. She shouldn’t have to be, though. She just wanted to visit a site and read things. It was very annoying.

    Drop Server Load

    Okay. So this part worked.

    Graph showing Server load on day 3 leveled out

    It only shows up starting day three because I didn’t flip DNS over right away. I had to turn off PageSpeed, upgrade PHP, make sure nginxcp was going to work with it… There was prep work. Day three, the little spikes vanished. You still get big ones because that’s when the server runs backups and upgrades. The little spikes are, normally, when I have a new post on the site.

    There’s been no perceptible change to bandwidth. All other sites on the server are, however, notably faster.

    End Result?

    It looks like CloudFlare worked. The stats say I’m using 25% less CPU with CloudFlare, which is interesting, but now that it’s baked, I want to try something else, just for grins and giggles.

  • Mailbag: SNI Incompatibility?

    Mailbag: SNI Incompatibility?

    Kim asks:

    You wrote an article which does a great job of explaining a number of things. My only question (comments appear to be closed so I could not post there) is the SNI – do you find that there are many people using browsers that are old enough that the SNI creates a problem? I have looked over the list of incompatibles and it does not seem to be that much of a risk, but I thought you might have more concrete information since you’ve been using the setup.

    This relates to how I set up my SSL certificates, which is to use Server Name Indications and have multiple certs on one server with one IP. And the question is “Do we care about the old browsers?”

    Let me quote my coworker.

    IE8 is EOL, XP is EOL. We can’t support things forever.

    XP makes up most of the sites that have issue with SNI so I’ve only found 0.006% of my visitors impacted.

    Yes, I did that math properly. I checked it a couple times.

    No. I’m not worried about SNI and I don’t care. We can’t support old things forever.