Job tracking improvements

 - Switch to using a Redis hash instead of a json object
 - add helper methods to support fetching created/updated timestamps
 - do not discard `created` timestamp on update
 - simplify job id mapping
 - sanity check `update()` to accept valid statuses only

all tests still pass :persevere:
should we throw an exception if an invalid status is attempted to pass in? This is probably only ever used internally, but still...