anchor.diff:          opts: Map<string,string> option
           _progress: int
       }
  +    member this.lockKey () = this.queue.toKey((this.jobId.ToString ()) + ":lock")
       member this.toData () =  
           let jsData = JsonConvert.SerializeObject (this.data)
           let jsOpts = JsonConvert.SerializeObject (this.opts)
  
positive.code:     let token = Guid.NewGuid ()
      let event = new Event<OxenEvent<'a>> ()
      let processJob job = async { 
              () 
          }
      let processStalledJob (job:Job<'a>) = 
          async { 
  
negative.code:     member this.remove () = async { raise (NotImplementedException ()) }
      member this.progress cnt = async { raise (NotImplementedException ()) }
      member this.takeLock (token, ?renew) = async {
              let nx = match renew with 
                       | Some x -> When.NotExists
                       | None -> When.Always     
              let value = (token.ToString ()) |> toValueStr
              let client:IDatabase = this.queue.client
              return! 
                  client.StringSetAsync (
                      this.lockKey (), 
                      value, 
                      Nullable (TimeSpan.FromMilliseconds (LOCK_RENEW_TIME)), 
                      nx 
                  ) |> Async.AwaitTask
          }
      member this.renewLock token = this.takeLock (token, true)
      member this.releaseLock token =
          let script = @"
              if redis.call("get", KEYS[1]) == ARGV[1] \n
              then \n
              return redis.call("del", KEYS[1]) \n
              else \n
              return 0 \n
              end \n" 
          this.queue.client.ScriptEvaluateAsync ()
      static member create (queue, jobId, data:'a, opts) = 
          async { 
              let job = { queue = queue; data = data; jobId = jobId; opts = opts; _progress = 0 }
  