Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add simple demo framework for Bedrock::Jobs; add requestID; add retries #15

Merged
merged 19 commits into from Apr 17, 2017

Conversation

quinthar
Copy link
Contributor

@quinthar quinthar commented Apr 12, 2017

This does the following:

  1. Adds a simple script that demonstrates Bedrock::Jobs with a trivial worker.
  2. Includes a few minor internal cleanups, with comments on each inside the diff.
  3. Provides a new API to fix https://github.com/Expensify/Expensify/issues/50199 (see https://github.com/Expensify/Web-Expensify/pull/17025)
  4. Fixes https://github.com/Expensify/Expensify/issues/50137

Sorry for globbing multiple issues and cleanups into a single PR; I wanted to use the demo harness I built to solve those other issues.

Assigning to @iwiznia for review this and https://github.com/Expensify/Web-Expensify/pull/17025

@@ -71,34 +71,37 @@
Client::configure($bedrockConfig);

$logger = Client::getLogger();
$logger->info('Starting BedrockWorkerManager', ['maxLoopIteration' => $maxLoopIteration]);
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just moving this line further up to keep the logging initialization code as early as possible.

if ($loopIteration === $maxLoopIteration) {
$logger->info("We did all our loops iteration, shutting down");
exit(0);
break;
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

exit(0) skips the "wait for children to finish" code at the end.

$loopIteration++;
$logger->info("Loop iteration", ['iteration' => $loopIteration]);

// Step One wait for resources to free up
while (true) {
// Get the latest load
if (!file_exists('/proc/loadavg')) {
throw new Exception('are you in a chroot? If so, please make sure /proc is mounted correctly');
}
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Moving the /proc/loadavg check here to keep it next to the sys_getloadavg() call that depends on it.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think we need to do this check every time the loop runs.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agreed we don't need to, but I think it's non-harmful to do it (eg, it's not a super expensive call given the relatively low the frequency of this loop), and makes the code read a lot cleaner to keep it where it's used.

clearstatcache(true, $versionWatchFile);
$newVersionWatchFileTimestamp = $versionWatchFile && file_exists($versionWatchFile) ? filemtime($versionWatchFile) : false;
$newVersionWatchFileTimestamp = ($versionWatchFile && file_exists($versionWatchFile)) ? filemtime($versionWatchFile) : false;
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just clarifying what this means with parenthesis as the precedence of the operators wasn't obvious to me at first.

$logger->info('Stopping BedrockWorkerManager, waiting for children');
$status = null;
pcntl_wait($status);
$logger->info('Stopped BedrockWorkerManager');
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Moving all this logic to the end of the outer loop, so it runs regardless of whether we're doing a graceful or abnormal shutdown.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@iwiznia Are you sure this shutdown code does anything?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes.

@@ -71,34 +71,37 @@
Client::configure($bedrockConfig);
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@iwiznia - Why do you manually copy all the values over to $bedrockConfig before passing it in, rather than just passing in $options?

}

// Add defaults
$jobName = @$options['jobName'] ?: '*'; // Process all jobs by default
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Moved this up closer to the usage description and updated the defaults to work out of the box with a minimum number of command line parameters.

while (true) {
if ($loopIteration === $maxLoopIteration) {
// Is it time to self destruct?
if ($maxIterations > 0 && $iteration >= $maxIterations) {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Renamed these variables to just use iterations rather than loopIterations.

/**
* Sample BedrockWorkerManager worker class.
*/
class SampleWorker extends BedrockWorker
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Adding this to provide a quick test and demonstration harness for how BWM works. In doing so I discovered that the Bedrock-PHP repo is incomplete, as BedrockWorker isn't included here. We need to extract that from the Expensify codebase and include in Bedrock-PHP/src instead.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If you are not moving BedrockWorker to this repo nor removing the Log call, I say we just leave the SampleWorker in the web repo for now and move it whenever we do that.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How about I just move SampleWorker to Bedrock-PHP as part of this PR, and remove its call to Log::, but we leave BedrockWorker where it is for now. So I'll make partial progress.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.

*/
public function run()
{
Log::info("Running SampleWorker for '{$this->job['name']}'");
Copy link
Contributor Author

@quinthar quinthar Apr 13, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a call to the Expensify Log class -- need to remove at some point, but I'm not doing it here.

@quinthar quinthar requested a review from cead22 April 13, 2017 01:04
@quinthar quinthar self-assigned this Apr 13, 2017
@quinthar quinthar changed the title [HOLD] Comment cleanup, shutdown logic tweaks Add simple test framework for Bedrock::Jobs Apr 13, 2017
@quinthar quinthar changed the title Add simple test framework for Bedrock::Jobs Add simple test framework for Bedrock::Jobs; add requestID Apr 13, 2017
@quinthar quinthar requested review from iwiznia and removed request for cead22 April 13, 2017 06:11
@quinthar quinthar changed the title Add simple test framework for Bedrock::Jobs; add requestID Add simple test framework for Bedrock::Jobs; add requestID; add retries Apr 13, 2017
$maxIterations = intval(@$options['maxIterations']) ?: -1; // Unlimited iterations by default

// Configure the Bedrock client with these command-line options
Client::configure($options);
Copy link
Contributor Author

@quinthar quinthar Apr 13, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I didn't see the value of $bedrockConfig as it seems to just be a direct copy of $options so I removed it. Please let me know if there was some hidden intent behind it, otherwise I'm assuming it was cruft (eg, maybe it previously had some kind of value, but some change obviated that value and this was just left over as an obsolete relic of the past).

src/Client.php Outdated
public static function setGlobalRequestID($globalRequestID)
{
// Override the global requestID
self::$globalRequestID = $globalRequestID;
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Note: this is called in Web-Expensify/_config.php and Web-Expensify/lib/Logger.php

src/Jobs.php Outdated
"jobID" => $jobID,
"data" => $data,
"repeat" => $repeat,
"idempotent" => "true",
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This header just indicates that it's safe to execute this command twice, as the result will be the same.

// Add defaults
$jobName = @$options['jobName'] ?: '*'; // Process all jobs by default
$maxLoad = floatval(@$options['maxLoad']) ?: 1.0; // Max load of 1.0 by default
$maxIterations = intval(@$options['maxIterations']) ?: -1; // Unlimited iterations by default
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I had a brief conversation with @cead22 about the "error control operator". I understand that we discourage it (though I don't understand why). Regardless, so far as I can tell we don't explicitly forbid it -- just discourage it -- which I'm interpreting as meaning it's up to the programmer's judgement. And in my judgement, the code above is far more readable than the alternative:

$jobName = isset($options['jobName']) ? $options['jobName'] : '*';
$maxLoad = (isset($options['maxLoad'] && floatval($options['maxLoad'])) ? floatval($options['maxLoad']) : 1.0;
$maxIterations = (isset($options['maxIterations'] && intval($options['maxIterations'])) ? intval($options['maxIterations']) ? -1;

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Now that we are on PHP7, we use the null coalescing operator and write this as $options['user'] ?? '*', which is better as it doesn't produce a silent notice.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh, sweet!

// Add defaults
$jobName = @$options['jobName'] ?: '*'; // Process all jobs by default
$maxLoad = floatval(@$options['maxLoad']) ?: 1.0; // Max load of 1.0 by default
$maxIterations = intval(@$options['maxIterations']) ?: -1; // Unlimited iterations by default
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Now that we are on PHP7, we use the null coalescing operator and write this as $options['user'] ?? '*', which is better as it doesn't produce a silent notice.


// Configure the Bedrock client with these command-line options
Client::configure($options);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

NAB: we were copying the bedrock specific configurations to a new array in order to not pass a ton of garbage options to the bedrock client. Now all bwm specific params are being passed to the client. Anyway, since I can't see any problem with it, I think is fine as is.

$loopIteration++;
$logger->info("Loop iteration", ['iteration' => $loopIteration]);

// Step One wait for resources to free up
while (true) {
// Get the latest load
if (!file_exists('/proc/loadavg')) {
throw new Exception('are you in a chroot? If so, please make sure /proc is mounted correctly');
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think we need to do this check every time the loop runs.

$logger->info('Stopping BedrockWorkerManager, waiting for children');
$status = null;
pcntl_wait($status);
$logger->info('Stopped BedrockWorkerManager');
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes.

/**
* Sample BedrockWorkerManager worker class.
*/
class SampleWorker extends BedrockWorker
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If you are not moving BedrockWorker to this repo nor removing the Log call, I say we just leave the SampleWorker in the web repo for now and move it whenever we do that.

src/Client.php Outdated
// Try idempotent requests up to three times, everything else only once
$numTries = (@$headers['idempotent'] === 'true') ? 3 : 1;
$response = null;
while($numTries-- && !$response)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Style: all these { should be on the same line.

src/Client.php Outdated
if ($numTries) {
$this->getLogger()->warning("Failed to connect, send, or receive request; retrying $numTries more times", ['message' => $e->getMessage()]);
} else {
$this->getLogger()->warning("Failed to connect, send, or receive request; not retrying", ['message' => $e->getMessage()]);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Log error instead of warning?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hm, well warning implies "this is something bad but not fatal", error implies "this is fatal and non-recoverable" to me.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's my point, when you retry, it's a warning, when you stopped retrying, is an error.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ahh got it, will do.

src/Client.php Outdated
@@ -146,6 +156,8 @@ public function call($method, $headers = [], $body = '')
// Include the requestID for logging purposes
if ($this->requestID) {
$headers['requestID'] = $this->requestID;
} else if (self::$globalRequestID) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does this work? I think $this->requestID will always be set, won't it?

Copy link
Contributor Author

@quinthar quinthar Apr 14, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How REQUEST_ID works today:

Actually no, it's not set by default. It's set to null in configure() by default, and that default is not overridden in BedrockWorkerManager.php. Indeed, I don't actually think that $this->requestID is set anywhere.

The closest we seem to do is this totally insane hack, but that only sets the requestID for Log::info(): it doesn't tell Bedrock to send it.

And the only reason Auth gets it is because we don't use Bedrock\Client and don't look at Log. Rather, we just use set it equal to the global REQUEST_ID constant directly.

What this PR does:

So, I've updated _config.php to set requestID so it's automatically set at the very start of the script, and also setting it inside the crazy hack.

Unfortunately, I'm realizing now what sucks about this is we will not update the REQUEST_ID constant -- it'll still be set to the REQUEST_ID of the parent BWM process. So this PR will create traceability through Bedrock, but not into Auth.

Proposing a better solution:

So I think the real solution would be to:

  1. Replace the REQUEST_ID constant with a $REQUEST_ID global variable, and then just use that everywhere. (I'm not sure why we're setting it separately inside Log -- we should just use the global.) This would also allow us to remove the crazy hack, which would be great. This would be pretty straightforward -- it's not actually used in that many places:
Davids-MacBook-Pro:Web-Expensify dbarrett$ grep -s -r REQUEST_ID *
_config.php: * REQUEST_ID yet. This will be set with the logID request parameter if it is
_config.php:if (!defined('REQUEST_ID') &&
_config.php:    define('REQUEST_ID', $_REQUEST['logID']);
_config.php:    define('REQUEST_ID', Log::generateID());
_config.php:Log::init(REQUEST_ID);
_config.php:Client::setGlobalRequestID(REQUEST_ID);
_config.php:    newrelic_add_custom_parameter('REQUEST_ID', REQUEST_ID);
_libfop.php:    $content['logID'] = REQUEST_ID;
_libfop.php:    $params['requestID'] = REQUEST_ID;
_tasks/Hit.class.php:            "logID"      => REQUEST_ID,
_testify/receiptUpload/testAll.php:    $parameters['logID'] = REQUEST_ID;
_testify/receiptUpload/testAll.php:    $parameters['email'] = 'AMEX_'.REQUEST_ID;
_testify/smartscan/autoScan.php:        "logID"      => REQUEST_ID,
api/amex/v1/lib/net.class.php:        $parameters['logID'] = REQUEST_ID;
api/amex/v1/lib/net.class.php:        $parameters['email'] = 'AMEX_'.REQUEST_ID;
externalLib/amazon-sdk-2.3.2/Aws/AutoScaling/Enum/ScalingActivityStatusCode.php:    const WAITING_FOR_SPOT_INSTANCE_REQUEST_ID = 'WaitingForSpotInstanceRequestId';
lib/Auth.php:        $headers['requestID'] = REQUEST_ID;
lib/Event.php:        $safeRequestID = DB_Analytics::escapeWithoutConnection(REQUEST_ID);
lib/Notification/Standard.php:        $params['requestID'] = REQUEST_ID;
lib/Report/Submit/Utils.php:        TechnicalContactNotifier::addMessage('Request ID '.REQUEST_ID);
Davids-MacBook-Pro:Web-Expensify dbarrett$ 
  1. Alternatively, we use something like runkit_constant_redefine() to just redefine it when we fork(). This requires installing a custom package, however.

  2. A third option would be to remove REQUEST_ID entirely... but I'm not sure really how to do that.

I think I lean toward (1) above. Thoughts?

Cc: @cead22

Copy link
Contributor

@cead22 cead22 Apr 14, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree that 1. seems like the best option. 2. has the drawbacks of requiring a package and maybe a lesser one that we're redefining a constant which can be confusing. As for 3. I don't even know what that would entail

src/Client.php Outdated
$this->sendRawRequest($rawRequest);
$response = $this->receiveRawResponse();
}
catch(ConnectionFailure $e)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not sure I get this retry logic and the commands being marked as idempotent.
This catch, will catch ConnectionFailure errors thrown either in reconnect or in recv. The ones in reconnect I'm not worried about, but the ones in recv I think require additional logic. So, when it fails on recv there's a chance that bedrock did actually process the command, but we failed to get the response from that command back for whatever reason. If this is the case, then:

  • We can't retry a GetJob command (well, we can, but we'll get a different job back and the one that we got previously would be stuck in RUNNING state).
  • We can retry a finish/retry/fail command, but we need to handle the response differently in case of a retry, because when retried those commands will return an error 405 (since the job needs to be in RUNNING state).

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, but I think that's already accounted for by flagging which commands are idempotent:

  • GetJobs is kind of idempotent. Yes, if it fails, it'll leave a job RUNNING forever. But that's not BWM's problem -- all it's going to do is call GetJobs again. So retrying GetJobs is safe.
  • Something like QueryJob is fine to retry.
  • Even something like FinishJob or RetryJob are fine. Either they work right, or they return a "this has already been finished" error. Either way, there's no harm in retrying.
  • However, something like CreateJob cannot be safely retried, as you might be trying to create a job that executes exactly once, so retrying could cause it to happen twice (or more).

Ultimately, flag it as idempotent: true if it's safe to retry -- and in almost all cases, it is.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Even something like FinishJob or RetryJob are fine. Either they work right, or they return a "this has already been finished" error. Either way, there's no harm in retrying.

This is the part that I think is wrong. So, you are going to retry and it's going to respond with a "this has already been finished" error, when that happens, we need to treat that error as a success instead or BWM will try to mark the job as failed (and fail in doing so too)

src/Client.php Outdated
$this->sendRawRequest($rawRequest);
$response = $this->receiveRawResponse();
// Try idempotent requests up to three times, everything else only once
$numTries = (@$headers['idempotent'] === 'true') ? 3 : 1;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why use "true" instead of true?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No idea why I did that. Fixing.

@quinthar
Copy link
Contributor Author

Ready for re-review.

* @param string $writeConsistency The bedrock write consistency we want to use
*
* @throws BedrockError
*/
public function __construct($host = null, $port = null, $failoverHost = null, $failoverPort = null, $connectionTimeout = null, $readTimeout = null, LoggerInterface $logger = null, StatsInterface $stats = null, $requestID = null, $writeConsistency = null)
public function __construct($host = null, $port = null, $failoverHost = null, $failoverPort = null, $connectionTimeout = null, $readTimeout = null, LoggerInterface $logger = null, StatsInterface $stats = null, $writeConsistency = null)
Copy link
Contributor Author

@quinthar quinthar Apr 15, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

FYI, so far as I can tell nobody ever uses this constructor for anything but the defaults. My sense is this many attributes in the constructor is pretty excessive, especially since we have a static configure() function. I'd vote we just remove the constructor, or remove configure(). I'm not sure we're getting much value by having both.

PS: Why is this named Client rather than just the more obvious Bedrock? I understand the full class is Expensify\Bedrock\Client, and I even understand that other libraries (eg, Intercom) use the Client moniker. But it makes searching for it really hard because the fully-qualified name is rarely used:

Davids-MacBook-Pro:Web-Expensify dbarrett$ grep -i -r -s 'new client' * | grep -i bedrock | grep .php: | grep -v vendor/ | grep -v externalLib/
_devportal/tools/bedrockJobManager/api.php:$bedrock = new Client();
_devportal/tools/harvester/personalAutoHarvest.php:        $bedrock = new Client();
_tasks/ParseResult.class.php:        $bedrock = new Client();
_tasks/ScanningAPI.class.php:        $bedrock = new Client();
_tests/integration/api/Policy/Connection/SetAutoSyncTest.php:        $bedrock = new Client();
_tests/integration/api/Policy/Connection/SetAutoSyncTest.php:        $bedrock = new Client();
_tests/integration/api/Policy/Connection/SetAutoSyncTest.php:        $bedrock = new Client();
_tests/integration/ChatBotTestUtils.php:        $bedrock = new Client();
_tests/integration/ChatBotTestUtils.php:        $bedrock = new Client();
_tests/integration/ChatBotTestUtils.php:        $bedrock = new Client();
_tests/integration/ChatBotTestUtils.php:        $bedrock = new Client();
_tests/integration/ChatBotTestUtils.php:        $bedrock = new Client();
_tests/integration/ChatBotTestUtils.php:        $bedrock = new Client();
_tests/integration/ChatBotTestUtils.php:        $bedrock = new Client();
_tests/integration/ChatBotTestUtils.php:        $bedrock = new Client();
_tests/integration/ChatBotTestUtils.php:        $bedrock = new Client();
_tests/integration/ChatBotTestUtils.php:        $bedrock = new Client();
_tests/integration/IntegrationTestUtils.php:        $db = new \Expensify\Bedrock\DB(new Client());
_tests/integration/IntegrationTestUtils.php:        $db = new \Expensify\Bedrock\DB(new Client());
_tests/integration/IntegrationTestUtils.php:        $db = new \Expensify\Bedrock\DB(new Client());
_tests/integration/lib/Bedrock/JobsTest.php:        self::$jobs = new Jobs(new Client());
_tests/integration/lib/Bedrock/JobsTest.php:        $db = new DB(new Client());
_tests/integration/lib/Bedrock/JobsTest.php:        $db = new DB(new Client());
_tests/integration/lib/Bedrock/JobsTest.php:        $db = new DB(new Client());
_tests/integration/lib/Bedrock/ParentJobsTest.php:        $jobs = new Jobs(new Client());
_tests/integration/lib/Bedrock/ParentJobsTest.php:        $jobs = new Jobs(new Client());
_tests/integration/lib/Bedrock/ParentJobsTest.php:        $jobs = new Jobs(new Client());
_tests/integration/lib/Bedrock/ParentJobsTest.php:        $jobs = new Jobs(new Client());
_tests/integration/lib/Bedrock/ParentJobsTest.php:        $jobs = new Jobs(new Client());
_tests/integration/lib/Bedrock/PriorityTest.php:        $jobs = new Jobs(new Client());
_tests/integration/lib/ChatBot/APITest.php:        $bedrock = new Client();
_tests/integration/lib/Tab/UtilsTest.php:        self::$bedrock = new DB(new Client());
lib/ChatBot/ChatBot.php:        $bedrock = new Client();
lib/ChatBot/Store/Chat.php:        $bedrock = new Client();
lib/ChatBot/Store/Chat.php:        $bedrock = new Client();
lib/ChatBot/Store/Event.php:            $bedrock = new Client();
lib/ChatBot/Store/Event.php:        $bedrock = new Client();
lib/ChatBot/Store/Event.php:        $bedrock = new Client();
lib/ChatBot/Store/Input.php:        $bedrock = new Client();
lib/ChatBot/Store/Input.php:        $bedrock = new Client();
lib/ChatBot/Store/Input.php:            $bedrock = new Client();
lib/ChatBot/Store/Input.php:        $bedrock = new Client();
lib/ChatBot/Store/State.php:        $bedrock = new Client();
lib/DomainSummary.php:            $bedrock = new Client();
lib/Notification/Standard.php:                $bedrock = new Client();
lib/Policy.php:            $bedrock = new Client();
lib/Policy.php:                    $bedrock = new Client();
lib/PolicyAPI.php:        $bedrock = new Client();
lib/Report/Reward.php:            $bedrockJobs = new Jobs(new Client());
lib/ReportUtils.php:        $bedrock = new Client();
script/bwm/EmailSendLogger.php:        $bedrock = new Client();
script/bwm/PolicyHarvester.php:        $bedrock = new Client();
script/bwm/PolicyHarvester.php:        $bedrock = new Client();
script/bwm/PolicySummaryEmail.php:            $bedrock = new Client();
script/bwm/UserHarvester.php:        $bedrock = new Client();
script/createDomainWorkers.php:$bedrock = new Client();
Davids-MacBook-Pro:Web-Expensify dbarrett$ 

@quinthar quinthar changed the title Add simple test framework for Bedrock::Jobs; add requestID; add retries Add simple demo framework for Bedrock::Jobs; add requestID; add retries Apr 15, 2017
@quinthar
Copy link
Contributor Author

@iwiznia Ready for re-review

throw new Exception('Maximum load must be greater than zero');
// Parse the command line and verify the required settings are provided
$options = getopt('', ['host::', 'port::', 'failoverHost::', 'failoverPort::', 'maxLoad::', 'maxIterations::', 'jobName::', 'logger::', 'stats::', 'workerPath::', 'versionWatchFile::', 'writeConsistency::']);
$workerPath = @$options['workerPath'];
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

$options['workerPath'] ?? null

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Per offline discussion, this is NAB

Client::configure($bedrockConfig);
// Add defaults
$jobName = $options['jobName'] ?? '*'; // Process all jobs by default
$maxLoad = floatval(@$options['maxLoad']) ?: 1.0; // Max load of 1.0 by default
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

floatval($options['maxLoad'] ?? 1.0)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Per offline discussion, this is NAB

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actually... on this does the ?? just implicitly do the error suppression on the left expression? So it'll work even if inside a function? That's pretty slick.

Copy link
Contributor

@iwiznia iwiznia Apr 17, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

$options['maxLoad'] ?? 1.0 is equivalent to (isset($options['maxLoad']) ? $options['maxLoad'] : 1.0)

// Add defaults
$jobName = $options['jobName'] ?? '*'; // Process all jobs by default
$maxLoad = floatval(@$options['maxLoad']) ?: 1.0; // Max load of 1.0 by default
$maxIterations = intval(@$options['maxIterations']) ?: -1; // Unlimited iterations by default
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

intval($options['maxIterations'] ?? -1)

$logger->info('Starting BedrockWorkerManager', ['maxIterations' => $maxIterations]);

// If --versionWatch is enabled, begin watching a version file for changes
$versionWatchFile = @$options['versionWatchFile'];
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

$options['versionWatchFile'] ?? null

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Per offline discussion, this is NAB

$this->sendRawRequest($rawRequest);
$response = $this->receiveRawResponse();
// Try idempotent requests up to three times, everything else only once
$numTries = @$headers['idempotent'] ? 3 : 1;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

isset($headers['idempotent']) ? 3 : 1

src/Client.php Outdated
$this->sendRawRequest($rawRequest);
$response = $this->receiveRawResponse();
}
catch(ConnectionFailure $e) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

NAB: this should be on the same line as the } above.

src/Client.php Outdated
// Try idempotent requests up to three times, everything else only once
$numTries = @$headers['idempotent'] ? 3 : 1;
$response = null;
while($numTries-- && !$response) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This comment wasn't answered.

// REQUEST_IDs.
mt_srand(getmypid());
$GLOBALS['REQUEST_ID'] = substr(base64_encode(sha1(mt_rand())),0,6); // random 6 character ID
$logger->info("Fork succeeded, child process, running job", [
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you change this text a bit so it's easier to search for parent vs child?

@iwiznia iwiznia merged commit 52ba40d into master Apr 17, 2017
@iwiznia iwiznia deleted the dbarrett_requestIDTweaks branch April 17, 2017 18:40
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

3 participants