ZeroMQ Message Router Dot Net
Recently I've been playing around with 0mq, specifically on the .net platform via clrzmq. For an open source project, 0mq's documentation is very good not only at explaining the product, but network communication patterns in general. Where it can/does fall down is when implementing outside the "cool kid" languages (C, Python, Ruby etc).
One of the documentation fails is that the "real" version you'd like to be using is the pre-release 3.x versions in nuget. This documentation fail, leads to another in the published examples which are for earlier versions of clrzmq. In particular about request/reply brokering found here.
I created a simpler version that actually compiles and does the proper brokering.
Documentation over tests
I'd rather have documentation than tests. Here's a concrete example of a horrible documentation fail. Take a look at the configuration example:
... cross-origin org.eclipse.jetty.servlets.CrossOriginFilter ... cross-origin /cometd/*
Are you kidding me? Dot Dot Dot?? What other configuration options are there? Using googlefu you come across questions like this. The poster in this case has no idea that for example allowedMethods and allowedHeaders cannot have * as a value... Because the documentation said so? No, because as we see the documentation doesn't even include these options as configuration value ... Unless you know what the prior punctuation somehow magically means.
So after looking up the code. I know what a valid configuration document should look like. What's wrong with that picture, SOLID people?
For a cross origin pre-flight request in jetty, you have to specify the headers to include ... And ... Then ... You also have ... to ... specify ... the ... actual ... HTTP ... Verbs ... That ... You'll ... Apply ...
cross-origin org.eclipse.jetty.servlets.CrossOriginFilter allowedOrigins * allowedMethods GET,POST,HEAD,PUT,DELETE allowedHeaders X-Requested-With,Content-Type,Accept,Origin,x-custom-header
Give me documentation, or give me death. - Patrick Henry
Scramble your facebook posts for privacy
I'm working on scrambls.com. A tool that allows you to manage who exactly can see your posts. How? Well if you were my real friend, you could see this message below:
[scrambls}ceitzVj2Q ☎⋝ ≉≋≩☍ ∽☊≖☇⊤⋓⊶ ⊑⋩≜ ≡⊼≇ ⋃∍⊲ ☈⊓∁⊙∧≮∭⊫⊂{]
If you think it's neat just comment on facebook and I'll send you an invite to get started
Parsnips
Validate Comma Separated Email Jquery Validation Engine
Another quick tip, utilizing underscore and validation engine
function validateEmail(field, rules, i, options) {
if (!_.all(field.val().split(","),
function(candidate) {
return $.trim(candidate).match(options.allrules.email.regex);
})
) return options.allrules.email.alertText;
}
haproxy http to https redirect
For those who are lazy, and don't want to understand haproxy thaaat well. In order to redirect all traffic from http to https use a variation of the following in your haproxy.cfg
#---------------------------------------------------------------------
# Redirect to secured
#---------------------------------------------------------------------
frontend unsecured *:80
redirect location https://foo.bar.com
#---------------------------------------------------------------------
# frontend secured
#---------------------------------------------------------------------
frontend secured *:443
mode tcp
default_backend app
#---------------------------------------------------------------------
# round robin balancing between the various backends
#---------------------------------------------------------------------
backend app
mode tcp
balance roundrobin
server app1 127.0.0.1:5001 check
server app2 127.0.0.1:5002 check
server app3 127.0.0.1:5003 check
server app4 127.0.0.1:5004 check
Create Ranges of Numbers with SQL
So in yesterdays post, the "monthly" requirement was going to be a challenge. Let's remind ourselves of what the requirement is:
3. “Monthly” = This will be 0-30, 31-60, 61-90, 91-120, 121-150, 151-180, etc
The problem is, I don't know how many of those groupings can exist. To solve this, I went into the bag of tricks and pulled out some recursion.
--SETS up aging bands in 30 day increments.
-- 0-30, 31-60, 61-90 until all inventory is accounted for.
CREATE TABLE #TempAgingBands (
AgingBandId int identity(0,1),
Start_Value int,
End_Value int,
Label nvarchar(20)
)
CREATE TABLE #TempAgingBandsEndValue (
AgingBandId int identity(0,1),
End_Value int
)
declare @Today date
declare @DogDate date
declare @MaxDays int
-- Get two dates, today and say some time in 1900's to show whats up
set @TODAY = GETDATE()
set @DOGDATE = DATEADD(DAY, -40150, @Today)
set @MaxDays = DATEDIFF(day, @DogDate, @Today) ;
-- Use Recursion to generate a list of start values (1, 31, 61, 91 etc) *NOTE You'll see how we'll change 1 to 0 below*
WITH Nbrs ( n ) AS (
SELECT 1 UNION ALL
SELECT 30 + n FROM Nbrs WHERE n < @maxDays )
INSERT INTO #TempAgingBands (Start_Value)
SELECT n FROM Nbrs
OPTION ( MAXRECURSION 32767 ) ;
-- Use recursion to generate list of end values (30, 60, 90, 120 etc)
WITH Nbrs ( n ) AS (
SELECT 30 UNION ALL
SELECT 30 + n FROM Nbrs WHERE n < @maxDays + 30 )
INSERT INTO #TempAgingBandsEndValue(End_Value)
SELECT n FROM Nbrs
OPTION ( MAXRECURSION 32767 ) ;
-- Put start and end values in the aging band table.
UPDATE #TempAgingBands
SET #TempAgingBands.End_Value = t2.End_Value
FROM #TempAgingBandsEndValue t2
WHERE #TEmpAgingBands.AgingBandId = t2.AgingBandId
-- The first record is 1,30 it should be 0,30 so update it.
UPDATE #TempAgingBands
SET Start_Value = 0
WHERE AgingBandId = 0
-- Update to get appropriate list of labels.
UPDATE #TempAgingBands
SET Label = (convert(varchar(7),Start_Value) + ' - ' + convert(varchar(7),End_Value))
-- See the results. #winning
select * from #TempAgingBands
Is there a way to update #TempAgingBands without creating a second temp table?
SQL Trickery
Today I had the unenviable task of trying to change an existing report which grouped line items into "aging bands", to have multiple aging bands. The requirement given was this:
The Dog Report currently has only one choice of Aging Band, which reports inventory in as follows:
0-180
181-270
271-330
331-365
366-455
>455We need to amend this Aging Band filter by offering 3 choices:
1. "Standard" = This will be the current aging bands above as presented in the attachment
2. "Bank" = This will be 0-180, 181- 270, 271-365, >365
3. "Monthly" = This will be 0-30, 31-60, 61-90, 91-120, 121-150, 151-180, etc
The previous implementation logic would tag each record with a grouping label based on how many days from today the record was indicating. Additionally, records in the future (DogDate < 0) would be grouped with 0 - 180... Here's the old logic:
CREATE TABLE #TempAgingBands (
AgingBandId int,
Start_Value int,
End_Value int,
Label nvarchar(20)
)
CREATE TABLE #TempDog (
OrderDogDays varchar(2),
DogDate date
)
-- Setup Aging Band table
INSERT INTO #TempAgingBands (AgingBandId, Start_Value, End_Value, Label)
VALUES ('0', 0, 180, '0 - 180'),
('1', 181, 270, '181 - 270'),
('2', 271, 330, '271 - 330'),
('3', 331, 365, '331 - 365'),
('4', 366, 455, '365 - 455'),
('5', 455, -1, '> 455')
--Some records are inserted into #TempDog
UPDATE #TempDog
SET OrderDogDays = (CASE WHEN DATEDIFF(day, DogDate, @Today) <= 180
THEN 0
WHEN DATEDIFF(day, DogDate, @Today) > 180 AND DATEDIFF(day, DogDate, @Today) <= 270
THEN 1
WHEN DATEDIFF(day, DogDate, @Today) > 270 AND DATEDIFF(day, DogDate, @Today) <= 330
THEN 2
WHEN DATEDIFF(day, DogDate, @Today) > 330 AND DATEDIFF(day, DogDate, @Today) <= 365
THEN 3
WHEN DATEDIFF(day, DogDate, @Today) > 365 AND DATEDIFF(day, DogDate, @Today) <= 455
THEN 4
WHEN DATEDIFF(day, DogDate, @Today) > 455
THEN 5
END)
The original developer didn't make use of his Start_Value and End_Value fields he defined... I wanted to use something more flexible to encapsulate any aging band definition they came up with... So here's my try:
UPDATE #TempDog SET OrderDogDays = (SELECT t.AgingBandId FROM #TempAgingBands t WHERE t.End_Value = -1 AND DATEDIFF(DAY, DogDate, @Today) > t.Start_Value UNION SELECT TOP 1 t.AgingBandId FROM #TempAgingBands t WHERE DATEDIFF(day, DogDate, @Today) >= t.Start_Value AND DATEDIFF(day, DogDate, @Today) <= t.End_Value AND t.End_Value != -1 AND DATEDIFF(day, DogDate, @Today) >= 0 UNION SELECT top 1 0 FROM #TempAgingBands t WHERE DATEDIFF(day, DogDate, @Today) < 0)
Can you think of a better way to do the third union?
Invade Wall Street or Whatever … Dude
Have you heard of the "Occupy Wall Street" movement? If you listen to Glenn Beck, these are the so called social justice brigade that is going to incite violence in the street.

Since when did hipsters become a political force that we became scared of? Are they going to burn all their vinyl on the streets until the man forgives their student loans? I mean for Pete's sake, they can't even manage to shower in the morning, let alone start a "revolution".
Catch the intellectual weight of some of their arguments. Such poised opinions can only come from someone who's spent their whole life surfing Goodwill's across America finding a plaid scarf to match his Guess glasses frames.
Hey 99 per-center, get a hair cut and a job. Dweeb.
Problem Solving Skills
Today I decided to take the code challenge of a startup full of really smart people doing a social networking site. They use interviewstreet.com for their code test, and I think it's a really good way to get the riff raff out if you're looking to hire someone who is really top notch.
You get 1 hour to complete the two interview questions. I managed to successfully complete one of the questions. I chalk up not completing the other question due to it being poorly written. It's possible that I just can't read too. I'll break down my thought process in solving the problem I did successfully solve, and maybe you too can know how I think.
Here is the problem:
A 7-digit number consists of 7 distinct digits (from 0-9). The product of the first 3 digits = product of central 3 digits = product of last 3 digits. Find the middle digit
There's a lot of cool math things going on in this problem:
- Transitivity Property
- 7 digit number, made up of unique digits -> Permutation
- Even though the problem states 0 is part of the set of numbers, we can't use it because 0 * any group of number is zero.
Ok, so knowing these characteristics of the problem, I set about a plan of attack:
- Find all permutations put them in a list.
- Iterate through list of permutations, use transitivity property to find answer
- ???
- profit
So I first set out to write a function to find all the permutations. How big of a problem is that?
P = n! / (n - k)!
With our problem set that's 181,440 possibilities. Ok, so I gotta write an efficient program to do that...
My head started hurting, surely there's a library that will help? Yes? Ok, python has itertools.permutations()... don't re-invent the wheel... So here's the final code:
import itertools
permutations = itertools.permutations([1,2,3,4,5,6,7,8,9],7)
for candidate in permutations:
val = candidate[0] * candidate[1] * candidate[2]
if val == candidate[2] * candidate[3] * candidate[4]:
if val == candidate[4] * candidate[5] * candidate[6]:
print candidate[3]
break
And the answer is 2. Cheers.
What prevents problems from being solved?
This is a question that I've pondered for a long time.
Take this one:
http://stackoverflow.com/questions/1610874/snireadsync-executing-between-120-500-ms-for-a-simple-query-what-do-i-look-for
Asked in October of 2009, our team was finally able to put this problem to rest, and more importantly improve site performance, database scalability and application cpu levels in a significant way. It took over a year to achieve, what essentially is a 3 line change in application server code and database configuration. So my question is, why did it take this long?
In order to answer this question, I think there are three categories of answer that are possible:
1. We didn't know how to solve it.
2. We didn't care to solve it.
3. We didn't know to care to solve it.
So which was it?
#1. We ended up solving the problem. We researched several alternatives and came up with a solution. This work in aggregate took about a "man week". By definition, this couldn't have been the cause of the delay.
#2. We did care to solve it. I was perplexed by the issue a year ago. However, I didn't have the experience/knowledge/data to raise the profile of the problem to something that should take priority.
#3. I think this is the winner. Until Seamlessweb purchased Dynatrace (which is awesome by the way), there was no way to reliably analyse the data and make a solid prediction which could be sold the business as a valuable proposition. But it wasn't just a tool which told us, essentially what we already knew. It was an organizational change which gave ownership of the technology platform, and in effect recognizing there was a problem to begin with. Once the business stake holders recognized that being concerned specifically with the technology platform as a whole, gave us the opportunity to sell the right solution to them at the right time.
The real value out of all this is to try and remember how we achieved this. Right now, all I remember is a lot of painful waiting. But maybe that's the proof of the adage all good things are worth waiting for.