diff --git a/2-generate-links.php b/2-generate-links.php index 6c47100..42b88cd 100644 --- a/2-generate-links.php +++ b/2-generate-links.php @@ -133,6 +133,8 @@ $ret->hSet($key, 'vcard_share_url_id', $shortenedLink); } } + + $ret->hSet($key, 'northstar_processed', 1); } // Batch processed. diff --git a/3-save-profile-updates-to-moco.php b/3-save-profile-updates-to-moco.php new file mode 100644 index 0000000..6e96d59 --- /dev/null +++ b/3-save-profile-updates-to-moco.php @@ -0,0 +1,128 @@ + Scan iterator value of last successfully saved batch. Works only with unchanged hashes +-l, --last A number of last successfully saved element. Works only with unchanged hashes +-h, --help Show this help +"); + +$args = (array) $opts; +$iterator = !empty($args['iterator']) ? (int) $args['iterator'] : NULL; + +// --- Imports --- +use Monolog\Formatter\LineFormatter; +use Monolog\Handler\StreamHandler; +use Monolog\Logger; +use Zend\ProgressBar\ProgressBar; + +// --- DS Imports --- + +// --- Logger --- +$logNamePrefix = REDIS_SCAN_COUNT + . '-' . ($iterator ?: 0) + . '-save-profiles-to-moco-'; + +// File. +$mainLogName = __DIR__ . '/log/' . $logNamePrefix . 'output.log'; +$logfile = fopen($mainLogName, "w"); +$logFileStream = new StreamHandler($logfile); +$logFileStream->setFormatter(new LineFormatter($output . "\n", $dateFormat)); +$log->pushHandler($logFileStream); +// Warning File. +$logfile = fopen(__DIR__ . '/log/' . $logNamePrefix . 'warning.log', "w"); +$logFileStream = new StreamHandler($logfile, Logger::WARNING); +$logFileStream->setFormatter(new LineFormatter($output . "\n", $dateFormat)); +$log->pushHandler($logFileStream); + +// Display main log filename. +echo 'Logging to ' . $mainLogName . PHP_EOL; + +// --- Progress --- +$progressData = (object) [ + 'current' => !empty($args['last']) ? (int) $args['last'] : 0, + 'max' => $redisRead->dbSize(), +]; +$progress = new ProgressBar( + $progressAdapter, + $progressData->current, + $progressData->max +); + +// --- Get data --- +// Retry when we get no keys back. +$redisRead->setOption(Redis::OPT_SCAN, Redis::SCAN_RETRY); +while($keysBatch = $redisRead->scan($iterator, REDIS_KEY . ':*', REDIS_SCAN_COUNT)) { + + // Initiate Redis transcation. + $ret = $redis->multi(); + + // Process batch. + try { + foreach($keysBatch as $key) { + // Monitor progress. + $progress->update( + ++$progressData->current, + $progressData->current . '/' . $progressData->max + ); + + // Load user from redis. + $mocoRedisUser = $redisRead->hGetAll($key); + + $mocoProfileUpdate = [ + 'phone_number' => $mocoRedisUser['phone_number'], + 'northstar_id' => $mocoRedisUser['northstar_id'], + 'vcard_share_url_id' => $mocoRedisUser['vcard_share_url_id'], + 'birthdate' => $mocoRedisUser['birthdate'], + 'Date of Birth' => $mocoRedisUser['birthdate'], + ]; + + $logMessage = '{current} of {max}, iterator {it}: ' + . 'Saving profile #{phone}, MoCo id {id}, fields: {fields}'; + + $log->debug($logMessage, [ + 'current' => $progressData->current, + 'max' => $progressData->max, + 'it' => $iterator, + 'phone' => $mocoRedisUser['phone_number'], + 'id' => $mocoRedisUser['id'], + 'fields' => json_encode($mocoProfileUpdate), + ]); + + $result = $moco->updateProfile($mocoProfileUpdate); + if ($result) { + $log->debug('Succesfully saved profile #{phone}, MoCo id {id}', [ + 'phone' => $mocoRedisUser['phone_number'], + 'id' => $mocoRedisUser['id'], + ]); + $ret->hSet($key, 'moco_profile_status', 'updated'); + } else { + $ret->hSet($key, 'moco_profile_status', 'failed'); + } + } + + // Batch processed. + $ret->exec(); + } catch (Exception $e) { + $ret->discard(); + throw $e; + } + + // Force garbage collector. + gc_collect_cycles(); +} + +// Set 100% when estimated $progressMax turned out to be incorrect. +if ($progressData->current != $progressData->max) { + $progress->update( + $progressData->max, + $progressData->max . '/' . $progressData->max + ); +} +$progress->finish(); + +$redisRead->close(); diff --git a/README.md b/README.md index 296f418..5e776f8 100644 --- a/README.md +++ b/README.md @@ -16,15 +16,16 @@ A collection of scripts for DoSomething Lose Your Vcard campaign ## Usage ### Step 1: Save all MoCo profiles to Redis ``` -$ php 1-get-users-from-moco.php --help Usage: 1-get-users-from-moco.php [options] Options: - -p, --page MoCo profiles start page, defaults to 1 - -l, --last MoCo profiles last page, defaults to 0 - -b, --batch <1-1000> MoCo profiles batch size, defaults to 100 - -h, --help Show this help + -p, --page MoCo profiles start page, defaults to 1 + -l, --last MoCo profiles last page, defaults to 0 + -b, --batch <1-1000> MoCo profiles batch size, defaults to 100 + -s, --sleep <0-60> Sleep between MoCo calls, defaults to 0 + --test-phones <15551111111,15551111112> Comma separated phone numbers. Intended for tests + -h, --help Show this help ``` ### Step 2: Match MoCo users to Northstar and generate new fields @@ -40,7 +41,15 @@ Options: ``` ### Step 3: Update MoCo profiles -TODO +``` +Usage: + 3-save-profile-updates-to-moco.php [options] + +Options: + -i, --iterator Scan iterator value of last successfully saved batch. Works only with unchanged hashes + -l, --last A number of last successfully saved element. Works only with unchanged hashes + -h, --help Show this help +``` ### Benchmarks ##### Batch 100, pages 30 diff --git a/src/MobileCommonsLoader.php b/src/MobileCommonsLoader.php index df20c8b..d3cdda3 100644 --- a/src/MobileCommonsLoader.php +++ b/src/MobileCommonsLoader.php @@ -70,4 +70,21 @@ function profilesEachBatch($page = 1, $limit = 0) { return $response->profiles; } + function updateProfile(Array $profile) { + $response = $this->moco->profiles_update($profile); + $success = ((string) $response['success']) === "true"; + if (!$success) { + $this->log->error( + 'Failed saving profile #{phone}: id: {id}, message: {message}', + [ + 'phone' => $profile['phone_number'], + 'id' => $response->error['id'], + 'message' => $response->error['message'], + ] + ); + return false; + } + return true; + } + }