public function perform()
    {
        Stats::decr('queued', 1);
        Stats::decr('queued', 1, Queue::redisKey($this->queue, 'stats'));

        if (Event::fire(Event::JOB_PERFORM, $this) === false) {
            $this->cancel();
            return false;
        }

        $this->run();

        $retval = true;

        try {
            $instance = $this->getInstance();

            ob_start();

            if (method_exists($instance, 'setUp')) {
                $instance->setUp();
            }

            call_user_func_array(array($instance, $this->method), array($this->data, $this));

            if (method_exists($instance, 'tearDown')) {
                $instance->tearDown();
            }

            $this->complete();
        } catch (Exception\Cancel $e) {
            // setUp said don't perform this job
            $this->cancel();
            $retval = false;
        } catch (\Exception $e) {
            $this->fail($e);
            $retval = false;
        }

        $output = ob_get_contents();

        while (ob_get_length()) {
            ob_end_clean();
        }

        $this->redis->hset(self::redisKey($this), 'output', $output);

        Event::fire(Event::JOB_DONE, $this);

        return $retval;
    }