Add yaml require so spec files can run in isolation.
Ensure phantomjs process stops.

Otherwise, it interferes with our tests for the forking server.
Fix Subscriber to not use Thread#raise.

It's unsafe and "should not be used for any purpose":

http://headius.blogspot.com/2008/02/rubys-threadraise-threadkill-timeoutrb.html

In addition, this brings back the semantic the Subscriber
used to have, that it is guaranteed to be listening when
control is returned to the caller. This makes use of
the subscriber much easier to reason about.

Yes, `wait_until` is not particularly elegant.  We could probably
refactor to use a monitor condition variable.  For now this
brings back the semantics we want and removes the use of the
dangerous `Thread#raise`.
Handle running a limited number of jobs directly.

Rather than hacking around it with stubbing #jobs.
Rework `thread_worker`.

- `thread_worker` isn't very descriptive of what it does.
  Rename it to `run_worker_concurrently_with`.
- Run the worker in the main thread, and check the condition
  in a separate thread.  This is more natural to me, and could
  matter if the user has some thread local variables in place
  and expects the worker to run in the same thread as their test.
- Fix `worker.stop!` so that it actually stops. Previously,
  it would stop the children but start new children.
- Stop using dangerous Thread#raise.
- Fix base worker's `jobs` method, so that if `@shutdown` has been
  set, it doesn't get stuck in a sleep loop.
- Use a mutex to prevent race conditions when another thread is stopping
  the worker.
- Include pid in logged message.
Rework job lock lost behavior.

- Don't use Thread#raise as it's dangerous.
- In prod we've observed behavior where memory leaks have
  occurred when JobLockLost happens, so it's better to
  `exit!(1)` the child and let the parent spawn a new one.
- For testing purposes, we don't want to run `exit!(1)` from
  the serial worker, because when it is run standalone in a test,
  we don't want the test process exiting suddenly.
- Instead, allow a callback, so the forking worker can configure
  it to die (since it'll take care of spawning a new child).
Use a queue for synchronization.

Rather than a busy wait loop.
Remove job_limit option.

It's not that generally useful (basically just tests),
and we can use an extension module instead.
Add `drain_worker_queues` helper method.
 
This is commonly needed in tests, as a means
to drain all jobs processed by a particular
worker.
Fix job lock lost behavior.

In prod, we were getting tons of killed child processes,
because we use the parent process's name as the worker name
for each child, so that EACH child gets the "job lock lost"
notification, and was doing `exit!(1)`, thus dying and causing
a later job lock lost for that job, causing a cascading effect.

Our fix is to only exit the child if it is running the job
that timed out.  We use a mutex to prevent race conditions
(i.e. where the child was processing a job a moment ago when
the subscriber thread checked, but no longer is).  If the
current job does not match the job lock lost message, it is
ignored, because it is probably meant for a different child process.
Surface thread errors.
Ensure `current_job` state doesn't linger during a sleep loop.
Gracefully handle there being no current job.
Remove vestigal `== 1`.
Improve spec a bit.
Use `channel` instead of `_channel`.
Remove unused attribute.
Fix typo.
Remove require.

This file was using a mutex but is no longer.
Rearrange helper methods.

- Put `redis_config` in the shared context that relies on it.
  This makes it clear why the YAML require was needed.
- Remove unused `redis_url`.