Refactor failure handling

* Split FailureInfo into ClientFailureInfo and FailureInfo, so that error codes can be propagated back from workers
* Change ErrorCode to a concrete class, instead of an interface, to allow it to be json serialized