jobbyphp / jobby

Manage all your cron jobs without modifying crontab. Handles locking, logging, error emails, and more.

Home Page:https://packagist.org/packages/hellogerard/jobby

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Serialization of closure failed: Serialization of 'Closure' is not allowed

wujekbogdan opened this issue · comments

I'm having a strange issue. I'm getting a:
Notice: Serialization of closure failed: Serialization of 'Closure' is not allowed in /path/to/php/file.php error.

This happens only when I use the use statement. So this code is causing the issue:

$app = new App();
$config = $app->config();
$logger = $app->getLogger();

$jobby->add('export-all', [
    'schedule' => $config->get("cron:export-all"),
    'closure'  => function () use ($app, $logger, $config) {
        // Do something
    },
]);

But this is fine:

$jobby->add('export-all', [
    'schedule' => $config->get("cron:export-all"),
    'closure'  => function () {
        $app = new App();
        $config = $app->config();
        $logger = $app->getLogger();
        // Do something
    },
]);

But, this is not a rule! Not always when I use the use statement I'm having this issue. But always when I'm getting this issue getting rid of the use statement solves the problem.


I know that Jobby is using SuperClosure internally, so it probably has something to to with SuperClosure not Jobby itself.

Closing in favor of #93

Hi, I know this issue is already closed, but I face the same is issue from the jobby-pdo example https://github.com/jobbyphp/jobby/blob/master/resources/jobby-pdo.php

➜  cp vendor/hellogerard/jobby/resources/jobby-pdo.php .
➜  nano jobby-pdo.php  # update autoload.php path
➜  php70 jobby-pdo.php 
PHP Notice:  Serialization of closure failed: The file containing the closure, "/home/arie/proj/Task/vendor/jeremeamia/SuperClosure/src/SerializableClosure.php(210) : eval()'d code" did not exist. in /home/arie/proj/Task/vendor/jeremeamia/SuperClosure/src/SerializableClosure.php on line 116

my environments: PHP 7.0.31 on Linux

@ariews Did you attempt the solution in #93 (comment)?

yes, I tried to add require_once __DIR__.'/vendor/autoload.php to the closure, but no luck.

I Just copied the jobby example, and update the vendor/autoload.php path, and adding vendor/autoload.php on closure. here is the file:

<?php

//
// This script demonstrates how to use jobby with a PDO-backend, which is used to
// save the jobby-cronjob/jobbies configuration.
//
// Adapt this file to your needs, copy it to your project-root,
// and add this line to your crontab file:
//
// * * * * * cd /path/to/project && php jobby-pdo.php 1>> /dev/null 2>&1
//

# update path
require_once __DIR__ . '/vendor/autoload.php';

// The table, which shall contain the cronjob-configuration(s).
$dbhJobbiesTableName = 'jobbies';

/*
 * For demo-purposes, an in-memory SQLite database is used.
 *
 * !!! REPLACE WITH YOUR OWN DATASOURCE!!!
 */
$dbh = new PDO('sqlite::memory:');
$dbh->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);

/*
 * Setup a test-fixture, having two jobs, first one is a system-cmd (date), second one is a Closure
 * (which is saved to pdo-database).
 */

$dbh->exec("
CREATE TABLE IF NOT EXISTS `$dbhJobbiesTableName`
(`name` VARCHAR(255) NOT NULL ,
 `command` TEXT NOT NULL ,
 `schedule` VARCHAR(255) NOT NULL ,
 `mailer` VARCHAR(255) NULL DEFAULT 'sendmail' ,
 `maxRuntime` INT UNSIGNED NULL ,
 `smtpHost` VARCHAR(255) NULL ,
 `smtpPort` SMALLINT UNSIGNED NULL ,
 `smtpUsername` VARCHAR(255) NULL ,
 `smtpPassword` VARCHAR(255) NULL ,
 `smtpSender` VARCHAR(255) NULL DEFAULT 'jobby@localhost' ,
 `smtpSenderName` VARCHAR(255) NULL DEFAULT 'Jobby' ,
 `smtpSecurity` VARCHAR(20) NULL ,
 `runAs` VARCHAR(255) NULL ,
 `environment` TEXT NULL ,
 `runOnHost` VARCHAR(255) NULL ,
 `output` VARCHAR(255) NULL ,
 `dateFormat` VARCHAR(100) NULL DEFAULT 'Y-m-d H:i:s' ,
 `enabled` BOOLEAN NULL DEFAULT TRUE ,
 `haltDir` VARCHAR(255) NULL , `debug` BOOLEAN NULL DEFAULT FALSE ,
 PRIMARY KEY (`name`)
)
");

$insertCronJobConfiguration = $dbh->prepare("
INSERT INTO `$dbhJobbiesTableName`
 (`name`,`command`,`schedule`,`output`)
 VALUES
 (:name,:command,:schedule,:output)
");
// First demo-job - print "date" to logs/command-pdo.log.
$insertCronJobConfiguration->execute(
    ['CommandExample', 'date', '* * * * *', 'logs/command-pdo.log']
);
// Second demo-job - a Closure which does some php::echo(). The Closure is saved to PDO-backend, too.
$secondJobFn = function() {
    # add autoload
    require_once __DIR__ . '/vendor/autoload.php';
    echo "I'm a function (" . date('Y-m-d H:i:s') . ')!' . PHP_EOL;
    return true;
};
$serializer = new SuperClosure\Serializer();

$secondJobFnSerialized = $serializer->serialize($secondJobFn);
$insertCronJobConfiguration->execute(
    ['ClosureExample', $secondJobFnSerialized, '* * * * *', 'logs/closure-pdo.log']
);

/*
 * Examples are now set up, and saved to PDO-backend.
 *
 * Now, fetch all jobbies from PDO-backend and run them.
 */

$jobbiesStmt = $dbh->query("SELECT * FROM `$dbhJobbiesTableName`");
$jobbies = $jobbiesStmt->fetchAll(PDO::FETCH_ASSOC);

$jobby = new \Jobby\Jobby();

foreach ($jobbies as $job) {
    // Filter out each value, which is not set (for example, "maxRuntime" is not defined in the job).
    $job = array_filter($job);

    try {
        $job['closure'] = $serializer->unserialize($job['command']);
        unset($job['command']);
    } catch (SuperClosure\Exception\ClosureUnserializationException $e) {
    }

    $jobName = $job['name'];
    unset($job['name']);
    $jobby->add($jobName, $job);
}

$jobby->run();

if you are curious about the modules:

➜  php70 -m
[PHP Modules]
apcu
Core
ctype
curl
date
dom
fileinfo
filter
gd
hash
iconv
imagick
json
libxml
mbstring
mcrypt
mysqli
mysqlnd
openssl
pcntl
pcre
PDO
pdo_mysql
pdo_pgsql
pdo_sqlite
pgsql
Phar
posix
readline
redis
Reflection
session
SimpleXML
SPL
sqlite3
standard
tokenizer
xml
xmlreader
xmlwriter
xsl
zip
zlib

[Zend Modules]