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
Conversation
bin/BedrockWorkerManager.php
Outdated
@@ -71,34 +71,37 @@ | |||
Client::configure($bedrockConfig); | |||
|
|||
$logger = Client::getLogger(); | |||
$logger->info('Starting BedrockWorkerManager', ['maxLoopIteration' => $maxLoopIteration]); |
There was a problem hiding this comment.
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.
bin/BedrockWorkerManager.php
Outdated
if ($loopIteration === $maxLoopIteration) { | ||
$logger->info("We did all our loops iteration, shutting down"); | ||
exit(0); | ||
break; |
There was a problem hiding this comment.
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'); | ||
} |
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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; |
There was a problem hiding this comment.
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'); |
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes.
bin/BedrockWorkerManager.php
Outdated
@@ -71,34 +71,37 @@ | |||
Client::configure($bedrockConfig); |
There was a problem hiding this comment.
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
?
bin/BedrockWorkerManager.php
Outdated
} | ||
|
||
// Add defaults | ||
$jobName = @$options['jobName'] ?: '*'; // Process all jobs by default |
There was a problem hiding this comment.
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) { |
There was a problem hiding this comment.
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 |
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done.
sample/SampleWorker.php
Outdated
*/ | ||
public function run() | ||
{ | ||
Log::info("Running SampleWorker for '{$this->job['name']}'"); |
There was a problem hiding this comment.
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.
bin/BedrockWorkerManager.php
Outdated
$maxIterations = intval(@$options['maxIterations']) ?: -1; // Unlimited iterations by default | ||
|
||
// Configure the Bedrock client with these command-line options | ||
Client::configure($options); |
There was a problem hiding this comment.
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; |
There was a problem hiding this comment.
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", |
There was a problem hiding this comment.
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.
bin/BedrockWorkerManager.php
Outdated
// 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 |
There was a problem hiding this comment.
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;
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oh, sweet!
bin/BedrockWorkerManager.php
Outdated
// 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 |
There was a problem hiding this comment.
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); |
There was a problem hiding this comment.
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'); | ||
} |
There was a problem hiding this comment.
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'); |
There was a problem hiding this comment.
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 |
There was a problem hiding this comment.
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) |
There was a problem hiding this comment.
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()]); |
There was a problem hiding this comment.
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?
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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) { |
There was a problem hiding this comment.
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?
There was a problem hiding this comment.
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:
- 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 insideLog
-- 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$
-
Alternatively, we use something like runkit_constant_redefine() to just redefine it when we
fork()
. This requires installing a custom package, however. -
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
There was a problem hiding this comment.
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) |
There was a problem hiding this comment.
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).
There was a problem hiding this comment.
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 jobRUNNING
forever. But that's not BWM's problem -- all it's going to do is callGetJobs
again. So retryingGetJobs
is safe.- Something like
QueryJob
is fine to retry. - Even something like
FinishJob
orRetryJob
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.
There was a problem hiding this comment.
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; |
There was a problem hiding this comment.
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
?
There was a problem hiding this comment.
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.
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) |
There was a problem hiding this comment.
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$
…nd reset it when forking)
@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']; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
$options['workerPath'] ?? null
There was a problem hiding this comment.
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 |
There was a problem hiding this comment.
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)
There was a problem hiding this comment.
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
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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 |
There was a problem hiding this comment.
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']; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
$options['versionWatchFile'] ?? null
There was a problem hiding this comment.
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; |
There was a problem hiding this comment.
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) { |
There was a problem hiding this comment.
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) { |
There was a problem hiding this comment.
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", [ |
There was a problem hiding this comment.
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?
This does the following:
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