Archive for category Uncategorized

The World’s Most Over Engineered BBQ Thermometer

So let me tell you a story.  Our story starts on Christmas morning, 2018.  I was hosting, my family had spent the night at my house christmas eve.  Being foodies we were beyond excited for the succulent 8lb prime grade prime rib that we would be cooking that day, outside on the large big green egg on my deck.  

We had an amazing Christmas with presents galore.  The grill was at the perfect temperature, the $160 cut of prime grade beef was prepped and it was time to cook.  It all went without a hitch as I loaded the grill up and placed the dual temperature probes – one in the meat one on the grill itself.  We waited, and waited. After about five hours it seemed like it should be done but the thermometer i was using at the time insisted no that it was not done.  So we waited and waited longer. Finally being very curious why it was taking so long I grabbed another instant read thermometer and checked it myself. At 120F we were going to remove it from the grill and let it gradually come up to a perfect rare doneness.  

When I plunged the thermometer into the roast I was horrified to see it was already at 142f.  It was overcooked by 22 degrees. My thermometer probe had failed and could not be trusted any more.  Something had to be done before next christmas.

But what to do?  As I stood in shock from the tragedy that had befallen us a plan suddenly became clear.  

There is only one thing to do.  Only one course of action that would be possible.  Build a Mult-Tenant Kubernetes Based BBQ Thermometer in Golang.  

Why had I not seen the need for this before?  By capturing more than one probe’s worth of data for each data source (two for grill, two for meat) then one could not fail without leaving detectable evidence of the failure.  Also, by tracking historical data and combining it with ambient weather conditions if both probes did fail you could compare past cooks with historical ones and against historical weather conditions to tell when the time was getting abnormally long for a cook.  

That was just the start though, eventually I would be able to build in AI to detect an event hours before it happened by comparing the temperature curve with historical data.  Gradient descent might be a simple way to do it.  

It needed to be run in Kubernetes because I would need the scalability of being able to go out to five thousand nodes.  We take our bbq very seriously.  

In the coming months I would build the thermometer.  Its not done yet, the code is all here to be reviewed but there is more work to be done.  I have gained a lot of insights by looking at the temperature curve of a cook. Specifically for the rather long cooks – Boston Butt or Brisket.  By graphically analyzing the temperature curve I’m able to spot the stall and to see that sometimes it happens sooner than the 160f that its supposed to.  Accurately detecting this can cut hours off of a cook.  

I’m actively working on this all the time.  The project is hosted in github:  https://github.com/ssargent/bbq  and uses Kubernetes, Golang, ReactJS, Redis, Postgres, Typescript and Javascript.  If you’d like to know more come check out the page on github.

, , ,

Leave a comment

Maximum call stack size exceeded when using Modals and AngularJS

Saw a really wierd error today, as you can guess from the title of the post it has to do with Maximum Call stack size exceeded, modals and AngularJS.   First a bit about the app.  I’m currently building a table of data, its basically a status report, so the url might be http://mysite.com/#/report/myreport  which would show you the list of data.  However I’m also building a detail page that will use a modal popup when you double click on a given row of the report.   I wanted this to be addressable so it would have its own url.  So basically i’ve got my angularjs route setup with an optional rowid parameter.

Request this:  http://mysite.com/#/report/myreport and you see the report show up.

Request this: http://mysite.com/#/report/myreport/32 and you see the report in the background with a modal overlay showing the details of row 32.

You can close the modal, view other records, the url changes as you do so.  All in all, its a pretty simple angularjs app.  No new concepts for me, I’ve used modal before, controllers etc all of it.  However, today when i wired up my code to load the modal when the page first loads, I saw an evil error in chrome:

Uncaught RangeError: Maximum call stack size exceeded.  jQuery.event.special.focus.trigger…. tons of jquery calls ….

Only in chrome, FIrefox acted a bit wierd, and IE well IE i’ll save for another day.  I tried googling it, all the results pointed to a recursive loop, but i had no recursive code.  Google was actually pretty unhelpful for this error.  I backed out all my changes for the instant modal popup functionality, and instead just wrote a log entry to the console.

The error didn’t appear, the log entry did appear, twice.  Somehow my controller was loading and running twice.  Googling that was helpful, I found this:  http://stackoverflow.com/questions/15535336/combating-angularjs-executing-controller-twice

It turned out I was doing the exact same thing.  I had no idea you were not supposed to register the controller at the top of the page if you were using routing.  Removing that single html attribute solved the dual log entry problem.  I then re-enabled my instant modal on load code, and that all worked without error as well.  Somehow with the controller loading twice and my code running at startup caused some wierd stack overflow.

Once it was loading only once the problem went away.  So here’s another post for google, I’m sure I’ll make this mistake again sometime,  probably in about three months or so.  Hopefully then I’ll google it and find my own blog post.

Leave a comment

Bundling AngularJS

There’s lots of posts out there on how to correctly bundle angularjs with any of the popular bundling tools.  I happen to use MVC’s built in bundling.  It works for me now, though I am looking at using less and gruntjs for some additional functionality.  Here’s a recent problem that I solved.  

I would see an error that looked something like this: 

Module Error
error in component $injector
Failed to instantiate module myApp due to:
Error: [$injector:unpr] http://errors.angularjs.org/undefined/$injector/unpr?p0=n
at Error ()
at http://myapp.mysite.com/bundles/app?v=xmkhVlgjOx7Eo5ltsK1SZpAavJM1dB6-bg-ujblqCgc1:1:130753
at http://myapp.mysite.com/bundles/app?v=xmkhVlgjOx7Eo5ltsK1SZpAavJM1dB6-bg-ujblqCgc1:1:143147
at i (http://myapp.mysite.com/bundles/app?v=xmkhVlgjOx7Eo5ltsK1SZpAavJM1dB6-bg-ujblqCgc1:1:141792)
at Object.r [as invoke] (http://myapp.mysite.com/bundles/app?v=xmkhVlgjOx7Eo5ltsK1SZpAavJM1dB6-bg-ujblqCgc1:1:141964)
at http://myapp.mysite.com/bundles/app?v=xmkhVlgjOx7Eo5ltsK1SZpAavJM1dB6-bg-ujblqCgc1:1:141398
at Array.forEach (native)
at r (http://myapp.mysite.com/bundles/app?v=xmkhVlgjOx7Eo5ltsK1SZpAavJM1dB6-bg-ujblqCgc1:1:131065)
at p (http://myapp.mysite.com/bundles/app?v=xmkhVlgjOx7Eo5ltsK1SZpAavJM1dB6-bg-ujblqCgc1:1:141201)
at sf (http://myapp.mysite.com/bundles/app?v=xmkhVlgjOx7Eo5ltsK1SZpAavJM1dB6-bg-ujblqCgc1:1:143261

I was pretty confused as to what was going on, I’d properly configured all of my controllers so they used an array like [‘$http’, ‘$q’, …] for injection.  What was going on.  

It turned it out it was one simple error.  In my app.js which handles the routing, I had code looking like this:

myApp .config(function ($routeProvider) {
$routeProvider.

That turned out to be the issue.  Once i refactored it to look like this:

myApp.config([“$routeProvider”, function ($routeProvider) {
$routeProvider.

It then bundled nicely and no javascript errors.  I should have noticed immediately when it said a module error, but I didn’t.  Hopefully this post gets into google and helps someone else.

 

, , , ,

Leave a comment

Fearless

Yesterday amidst a sea of tears and in front of a hot grill I finished reading Fearless – http://fearlessnavyseal.com   I was delaying my grilling responsibilities for the evening to cram in the last few pages.  I love reading and recently I’ve been on a biography kick, I read Howard Wasdin’s biography a year or so ago, and Chris Kyle’s biography just this weekend.  All of these books, have been biographies of Navy Seals, and when on friday I saw a book titled “Fearless” the story of Seal Team Six member advertised on Amazon, I gave it a look and ended up buying it.

This book I knew would be different, the others were written by the SEALs themselves, sometimes with co-authors.  This book, Adam Brown’s story was written after he was killed in action.  I knew it would be sad, I knew it would be touching.  Even though I was armed with that knowledge, I wasn’t prepared for this book. I’ll challenge anyone to read the first two pages, and put the book down from there.  I couldn’t and I don’t think you’ll be able to either.

Put quite simply, I’ve never read anything that had that big an impact on me before.  I found myself in awe and inspired by Adam Brown in many parts of the book, and in full tears in many other parts.  The story is so unbelievable that it couldn’t be fiction.  The old adage or saying, that the Truth is Stranger than fiction is very true for this story.   I won’t give away details, and please if you have read this book do not post spoilers in the comments.   I would be lying if I said after reading this book I wouldn’t look at life at least a little differently.

It is a book about the military, it is a book about a warrior.  Most of all though its a book about humanity, the struggles and obstacles that Adam had to overcome.  Definitely read this book.

Leave a comment

Major News Coming Soon

Keep tuned, and check back soon.  Perhaps Friday, at say 5-ish eastern time.  There’s big news coming to this blog.  No Hints and I’m not telling till Friday 🙂

Leave a comment

Database Schema Changes with Postgresql

I’ve been playing with linux recently and really enjoying it.  Quite quickly however I began looking for a good database to use in linux.  The obvious choice if you look around the internets is mysql.  Its the easy one to use, most people use it and as such there’s a ton of documentation etc..  Well for those that know me, the easiest and simplest way is not always what I choose.  So I began to look at postgresql.  PostgreSQL has more in common with databases like Oracle or DB2 than mysql, for some this is a minus but for me that’s a definite plus.  I’ve a lot of oracle experience and skills that can be applied to postgresql quite nicely.  One thing I absolutely love in postgres & oracle is the create or replace functionality for functions.  Gone are the days of if object_id(my_function) is not null…  now I can just create or replace my_function.  That’s killer in my opinion.  So now I’ve got my database (postgresql 9.0) and its time to create some tables.  This was a bit of a dilemma for me, in my native environment (oracle or sql server) I create database change scripts that safely and reentrantly ( you can run repeatedly w/o error) create the objects that are needed in a transactional manner.  But how to do this in postgresql?  Well this post is about what I’ve figured out, and how I’m currently solving that problem.

First, take a look at my postgresql github repository.  What I wanted was a way to have controlled, scripted database changes that were transactional.  They would either entirely succeed or entirely fail and leave the database unmodified.  Also the individual script files would have to have a way of saying I am change #X and I need change #Y to be present first.

Below is how I’ve accomplished this.  What this does is it applies database change 1.0.0 to a database that is of change 0.0.0  (see dbc_0.0.0 in the github rep for how schemaversion, and the initial record get put in place).  Hopefully this is of some help to someone.

create or replace function dbc_1_0_0() returns void as
$$
declare
_old_major integer := 0;
_old_minor integer := 0;
_old_revision integer := 0;
_major integer := 1;
_minor integer := 0;
_revision integer := 0;
_schemaname varchar := 'my-application-name';
begin
if exists(select 1 from schemaversion where major = _old_major and minor = _old_minor and revision = _old_revision and schemaname = _schemaname and current_version = true) then
create sequence user_id_seq;
create table users
(
userid int8 default nextval('user_id_seq') not null,
email varchar(64) not null,
password varchar(128) not null,
fullname varchar(64) not null,
created_date timestamptz not null,
modified_date timestamptz not null,
constraint pk_users_userid primary key (userid)
);
update schemaversion set current_version = false where major = _old_major and minor = _old_minor and revision = _old_revision and schemaname = _schemaname;
insert into schemaversion
(major,minor,revision,schemaname,installed_date,current_version)
values
(_major,_minor,_revision,_schemaname,current_timestamp, true);
else
select 'Missing prerequisite schema update ' || _schemaname || 'version ' || _major || '.' || _minor || '.' || _revision;
end if;
exception
when others then
raise exception 'caught exception - (%) - when applying update %.%.% to % ', SQLERRM, _major,_minor,_revision,_schemaname;
end
$$
language 'plpgsql';
select dbc_1_0_0();
drop function dbc_1_0_0();

 

1 Comment