The Daily Parker

Politics, Weather, Photography, and the Dog

The most popular drink in the universe

According to Douglas Adams, every planet in the universe has some variation on the drink gin & tonic. On this planet, the drink may have changed history:

Without quinine, malaria would have felled the conquerors; without gin to alleviate the bitterness of this highly effective anti-malarial, the soldiers would have refused to down their medicine.

The ability to withstand malaria helped Britain to conquer half of Africa and keep India subjugated (more or less). So much misery, engendered by one of the world’s most inspired taste combinations.

Of course, cold gin with a splash of dry vermouth works just fine for those of us in more temperate climates. Put olives in for perfection.

Ricketts tells the rooftop owners to sod off

Even though the Cubs are officially the second-worst team in baseball right now, Cubs owner and chairman Tom Ricketts is tired of negotiating with the neighborhood:

The Cubs announced early Thursday that they plan to ask the city to approve more signs in the outfield at Wrigley Field, a move that comes after "endless hours" of negotiating with rooftop owners have gone nowhere, Cubs Chairman Tom Ricketts said in a video.

In the six-minute video to fans, Ricketts blamed rooftop owners for delaying the renovation of the field, saying "Despite the city's approval and our clear contractual rights, they plan to file lawsuits to stop our renovation and expansion plans."

Well, sort of. The Cubs agreed to a 20-year contract with the rooftop owners in 2004, so the rooftop owners actually have a case.

Of course, a Jumbotron in left field is exactly what the organization needs to win ballgames. I mean, there couldn't be any other reason, right?

Two Gentlemen of Verona, second set

Three more photos from Sunday's publicity shots.

Shaina Summerville and Stephen McClure:

Shaina Summerville and Parker, behaving for about 30 seconds:

Zach Blackwell, Shaina Summerville, and Stephen McClure:

My direction for that last one was, "Imagine something horrible. It's Sarah Palin. She's got a gun. She's coming toward you. And she's naked." They look truly horrified, don't they?

Cubs beat Yankees in squishy game

I went to yesterday's Cubs-Yankees game at Wrigley and was very happy in the middle of it that our seats are under the awning.

The Cubs won 6-1 while a nearby thunderstorm dumped a centimeter of rain on the park in the top of the 9th:

Maybe rain is Tanaka's Kryptonite. As rain started to fall at Wrigley, the Cubs were able to total as many hits in the third inning as they did against Tanaka last month. Baker singled to lead off the third, moved up on Hammel's sacrifice, and scored on Bonifacio's single.

Luis Valbuena doubled to lead off the fourth, and one out later, scored on Olt's single to make it 2-0. Valbuena went 0-for-3 in New York against Tanaka, and is the first player to get three hits off Tanaka in a single game.

"I had more of an idea," Valbuena said.

Apparently it was Derek Jeter's last game:

Outgoing Yankees captain Derek Jeter, who was presented with a No. 2 tile from the scoreboard in a pregame ceremony, had a pair of singles — the 3,354th and 3,355th of his career.

He grounded out to shortstop Starlin Castro with the bases loaded to end the game.

At that point, weather radar showed the rain ending soon, but not soon enough. Between the park and the #22 bus across the street I got drenched. I think my shoes are still damp.

How not to get your face eaten by a dog

Good advice:

Rule 1: You probably shouldn't approach a stranger's dog. Well, ok, that's not exactly true. But you should never simply approach a stranger's dog without asking - from a distance - if it's ok. Some people don't want their dogs to interact with people they come across on the street. Some dogs look well-behaved but when they get around a human that is not their owner, they freak out. Even the most well-behaved dog is still an animal that acts on instinct and could flip out and attack if scared. Keep that in mind.

Rule 2: If you must approach a stranger's dog and the owner gives you permission, you shouldn't simply start petting it. Some dogs are picky about where they like to be touched.

Fortunately for people, Parker is a pushover and likes pats. Unfortunately for people, Parker does not like it when other dogs approach while he's on-leash. And yet stupid people let their dogs pull them towards us while yelling "Can he say hi?" No, he may not say hi, unless you want to pay both vet bills.

So pat Parker, but be careful of strange dogs you meet on the street.

That seemed to go well...

The deployment, I mean. Everything works, at least on the browsers I've used to test it. I ran the deployment three times in Test first, starting from a copy of the Production database each time, so I was as confident as I could be when I finally ran it against the Production database itself. And, I made sure I can swap everything back to the old version in about 15 minutes.

Also, I snuck away to shoot publicity photos for Spectralia again, same as last year. I'll have some up by the end of the week, after the director has seen them.

Scary software deployment

Jez Humble, who wrote the book on continuous delivery, believes deployments should be boring. I totally agree; it's one of the biggest reasons I like working with Microsoft Azure.

Occasionally, however, deploying software is not at all boring. Today, for example.

Because Microsoft has ended support for Windows Server 2008 as of next week, I've upgraded an old application that I first released to Azure in August 2012. Well, actually, I updated it back in March, so I could get ahead of the game, and the boring deployment turned horrifying when half of my client's customers couldn't use the application because the OS upgrade broke their Windows XP/IE8 user experience. Seriously.

All of my client's customers have now upgraded to Chrome, IE11, or Firefox, and I've tested the app on all three browsers. Everything works. But now I have to redeploy the upgrade, and I've got a real feeling of being once-bitten.

The hard part, the part that makes this a one-way upgrade, is a significant change to the database schema. All the application's lookup lists, event logging, auditing, and a few other data structures, are incompatible with the current Production version. Even if there weren't an OS upgrade involved, the database changes are overdue, so there is no going back after this.

Here are the steps that I will take for this deployment:

  1. Copy current Production database to new MigrationTest database
  2. Upgrade MigrationTest database
  3. Verify Test settings, connection strings, and storage keys
  4. Deploy Web project to Test instance (production slot)
  5. Validate Test instance
  6. Deploy Worker project to Test instance (production slot)
  7. Validate Worker instance
  8. Shut down Production instance
  9. Back up Production database to bacpac
  10. Copy Production database within SQL instance
  11. Upgrade Production database
  12. Verify Production settings, connection strings, and storage keys
  13. Deploy solution to Production instance (staging slot)
  14. Validate Production Web instance
  15. Validate Production Worker instance
  16. VIP swap to Production

Step 1 is already complete. Step 2 will be delayed for a moment while I apply a patch to Visual Studio over my painfully-slow internet connection (thanks, AT&T!). And I expect to be done with all of this in time for Game of Thrones.

How to look up Azure table data by ID

Short answer: You can't. So don't try.

Back in 2007, when I wrote a scheduling application for a (still ongoing!) client, Azure was a frustrating research project at Microsoft. Every bit of data the application stored went into SQL Server tables including field-level auditing and event logs.

The application migrated to Azure in August 2012, still logging every audit record and event to SQL tables, which are something like 10x more expensive per byte than Azure Table Storage. Recently, I completed an upgrade to the Inner Drive Extensible Architecture™ so it can now use Azure table storage for both.

The old application knew nothing about this. So upgrading the application with the new IDEA bits worked fine for writing to the audit and event logs, but completely broke reading from them.

Here's the code the app uses displaying a specific audit record so an administrator can see the field-level details:

// Get the repository from Castle IoC:
var repo = ActiveContainer.Instance.Container.Resolve<IAuditRepository>();

// Get the individual audit record by ID:
var audit = repo.Find(id);

That's great if the audit record uses a database identity key. Unfortunately it does not; it uses an Azure partition and row key combination.

I agonized for a couple of days how to fake database identities in Azure, or how to write a mapping table, or do some other code- or data-intensive thing or another. Then this afternoon, epiphany!

The user viewing an audit record is doing it in the context of reviewing a short list of audit headers. They click on one of these headers to pop up the detail box. The detail box uses the audit ID like this: https://scheduler.myclient.com/Auditing/AuditDetailViewer/12345.

It turns out, the only time a user cares about audit details is when she has the audit list right in front of her. So the audit ID is irrelevant. It only has to be unique within the context of the user's experience.

Here's the solution. In the Auditing class, which generates the audit list, I do this:

foreach (var item in orderedAudits)
{
	// Temporal cohesion: Add identity to Audit before using
	AddIdentity(item);
	Cache(item);
	CreateAuditRow(placeHolder, isObjectSpecified, item, timeZone);
	// End temporal cohesion
}

The cache uses least-frequently-used scavenging with a capacity of 512 items. (If the one user who cares about auditing ever needs to see more than 512 audit items in one list, I'll coach him not to do that.) Items live in the cache until it gets full, at which time the least-used ones are removed. This lets me do this in the audit detail view's control code:

var audit = Auditing.Find(id);

The Auditing.Find method simply plucks the item from the cache. If it returns null, oops, the audit details are missing or have expired from the cache, sorry. Just rerun the list of audits that you just clicked on.

I'm going to use a similar approach to the event log.