-
Notifications
You must be signed in to change notification settings - Fork 751
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
[GOBBLIN-1773] Fix bugs in quota manager #3636
Changes from all commits
a18fe16
4fff7c5
3fa7fba
acd20fc
d5e22ea
b9e6fab
e386585
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -27,6 +27,7 @@ | |
import java.util.concurrent.TimeUnit; | ||
|
||
import org.apache.commons.lang3.reflect.ConstructorUtils; | ||
import org.apache.gobblin.util.reflection.GobblinConstructorUtils; | ||
import org.slf4j.Logger; | ||
import org.slf4j.LoggerFactory; | ||
|
||
|
@@ -101,6 +102,9 @@ public class Orchestrator implements SpecCatalogListener, Instrumentable { | |
@Setter | ||
private FlowStatusGenerator flowStatusGenerator; | ||
|
||
private UserQuotaManager quotaManager; | ||
|
||
|
||
private final ClassAliasResolver<SpecCompiler> aliasResolver; | ||
|
||
private Map<String, FlowCompiledState> flowGauges = Maps.newHashMap(); | ||
|
@@ -150,6 +154,8 @@ public Orchestrator(Config config, Optional<TopologyCatalog> topologyCatalog, Op | |
} | ||
this.flowConcurrencyFlag = ConfigUtils.getBoolean(config, ServiceConfigKeys.FLOW_CONCURRENCY_ALLOWED, | ||
ServiceConfigKeys.DEFAULT_FLOW_CONCURRENCY_ALLOWED); | ||
quotaManager = GobblinConstructorUtils.invokeConstructor(UserQuotaManager.class, | ||
ConfigUtils.getString(config, ServiceConfigKeys.QUOTA_MANAGER_CLASS, ServiceConfigKeys.DEFAULT_QUOTA_MANAGER), config); | ||
} | ||
|
||
@Inject | ||
|
@@ -247,6 +253,13 @@ public void orchestrate(Spec spec) throws Exception { | |
+ "concurrent executions are disabled for this flow.", flowGroup, flowName); | ||
conditionallyUpdateFlowGaugeSpecState(spec, CompiledState.SKIPPED); | ||
Instrumented.markMeter(this.skippedFlowsMeter); | ||
if (!((FlowSpec)spec).getConfigAsProperties().containsKey(ConfigurationKeys.JOB_SCHEDULE_KEY)) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This can come in a later PR but we should have a static function to check if a FlowSpec is adhoc or not in the FlowSpec class |
||
// For ad-hoc flow, we might already increase quota, we need to decrease here | ||
Dag<JobExecutionPlan> jobExecutionPlanDag = specCompiler.compileFlow(spec); | ||
for(Dag.DagNode dagNode : jobExecutionPlanDag.getStartNodes()) { | ||
quotaManager.releaseQuota(dagNode); | ||
} | ||
} | ||
|
||
// Send FLOW_FAILED event | ||
Map<String, String> flowMetadata = TimingEventUtils.getFlowMetadata((FlowSpec) spec); | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -328,10 +328,11 @@ public AddSpecResponse onAddSpec(Spec addedSpec) { | |
return new AddSpecResponse<>(response); | ||
} | ||
|
||
// Check quota limits against run immediately flows or adhoc flows before saving the schedule | ||
// Check quota limits against adhoc flows before saving the schedule | ||
// In warm standby mode, this quota check will happen on restli API layer when we accept the flow | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. afaik FlowConfigV2ResourceLocalHandler and FlowCatalog are not doing quota check on adding the spec. Where do we do the check in API layer? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I see did not notice the difference in warm standby mode. |
||
if (!this.warmStandbyEnabled && (!jobConfig.containsKey(ConfigurationKeys.JOB_SCHEDULE_KEY) || PropertiesUtils.getPropAsBoolean(jobConfig, ConfigurationKeys.FLOW_RUN_IMMEDIATELY, "false"))) { | ||
// This block should be reachable only for the first execution for the adhoc flows (flows that either do not have a schedule or have runImmediately=true. | ||
if (!this.warmStandbyEnabled && !jobConfig.containsKey(ConfigurationKeys.JOB_SCHEDULE_KEY)) { | ||
// This block should be reachable only for the execution for the adhoc flows | ||
// For flow that has scheduler but run-immediately set to be true, we won't check the quota as we will use a different execution id later | ||
if (quotaManager.isPresent()) { | ||
// QuotaManager has idempotent checks for a dagNode, so this check won't double add quotas for a flow in the DagManager | ||
try { | ||
|
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 we deem this function not safe to use as it does not read from the shared threadpool, would it be appropriate to make MySqlStateStore.newDataSource package private?