All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.google.appengine.api.datastore.dev.DefaultHighRepJobPolicy Maven / Gradle / Ivy

Go to download

SDK for dev_appserver (local development) with some of the dependencies shaded (repackaged)

There is a newer version: 2.0.31
Show newest version
/*
 * Copyright 2021 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     https://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.google.appengine.api.datastore.dev;

import com.google.appengine.api.datastore.Key;
import java.util.Map;
import java.util.Random;

/**
 * An implementation of {@link HighRepJobPolicy} in which a user-defined percentage of jobs do not
 * apply. The percentage applies to both new (initial write) and existing (roll forward) jobs. The
 * user can also provide a random seed, which can be used to make the behavior of this class
 * deterministic in tests.
 *
 */
public class DefaultHighRepJobPolicy implements HighRepJobPolicy {

  /**
   * A long that will be used as the seed for the {@link Random} that determines whether or not a
   * job application attempt fails. Must be parsable via {@link Long#parseLong(String)}. If not
   * provided we use the current time (in millis) as the seed.
   */
  public static final String RANDOM_SEED_PROPERTY =
      "datastore.default_high_rep_job_policy_random_seed";

  /**
   * A float >= 0 and <= 100 representing the percentage of job application attempts that will fail.
   * Must be parsable via {@link Float#parseFloat(String)}. Any portion of the value beyond two
   * decimal places will be truncated. If not provided we set the percentage to 0.
   */
  public static final String UNAPPLIED_JOB_PERCENTAGE_PROPERTY =
      "datastore.default_high_rep_job_policy_unapplied_job_pct";

  /**
   * The default unapplied job percentage. Used if no value is provided for
   * UNAPPLIED_JOB_PERCENTAGE_PROPERTY.
   *
   * 

Note that the dev appserver and dev appserver integration tests set this property explicitly * in order to provide HRD-like consistency by default. * *

Therefore this value is the default value only for unit tests. */ private static final float DEFAULT_UNAPPLIED_JOB_PCT = 0; /** * The ceiling for all random values we generate. We have a maximum precision of 2 decimal places. */ /* @VisibleForTesting */ static final int RANDOM_CEILING = 100 * 100; /** * Multiply the unapplied job percentage by this number to map it into the range [0, * RANDOM_CEILING]. */ private static final int UNAPPLIED_JOB_PCT_MULTIPLIER = RANDOM_CEILING / 100; /* @VisibleForTesting */ final Random random; /** * When we generate a random number that is greater than or equal to this cutoff, the job applies. * When the number is less than this cutoff, the job does not apply. */ /* @VisibleForTesting */ final int unappliedJobCutoff; /** * Constructs a {@code DefaultHighRepJobPolicy}. * * @param unappliedJobSeed The seed to use for random number generation. * @param unappliedJobPercentage The percentage of jobs that should fail to apply. This percentage * applies to both new jobs and attempts to roll forward existing unapplied jobs. */ public DefaultHighRepJobPolicy(long unappliedJobSeed, float unappliedJobPercentage) { random = new Random(unappliedJobSeed); if (unappliedJobPercentage < 0) { throw new IllegalArgumentException( String.format( "Unapplied job percentage must be >= 0 (received %f)", unappliedJobPercentage)); } if (unappliedJobPercentage > 100.00d) { throw new IllegalArgumentException( String.format( "Unapplied job percentage must be <= 100.00 (received %f)", unappliedJobPercentage)); } unappliedJobCutoff = (int) (unappliedJobPercentage * UNAPPLIED_JOB_PCT_MULTIPLIER); } /** * Constructs a {@code DefaultHighRepJobPolicy} from a property map. * * @param localDatastoreServiceProperties The property map. */ DefaultHighRepJobPolicy(Map localDatastoreServiceProperties) { this( getUnappliedJobSeedPropValue(localDatastoreServiceProperties), getUnappliedJobPctPropValue(localDatastoreServiceProperties)); } private static float getUnappliedJobPctPropValue( Map localDatastoreServiceProperties) { String unappliedJobPctProp = localDatastoreServiceProperties.get(UNAPPLIED_JOB_PERCENTAGE_PROPERTY); if (unappliedJobPctProp != null) { return Float.parseFloat(unappliedJobPctProp); } return DEFAULT_UNAPPLIED_JOB_PCT; } static long getUnappliedJobSeedPropValue(Map localDatastoreServiceProperties) { String unappliedJobSeedProp = localDatastoreServiceProperties.get(RANDOM_SEED_PROPERTY); if (unappliedJobSeedProp != null) { return Long.parseLong(unappliedJobSeedProp); } // User didn't provide a seed so use the current time return System.currentTimeMillis(); } private boolean shouldApply() { // Gives us a value x in between 0 (incl) and RANDOM_CEILING (excl). return nextRandomInt() >= unappliedJobCutoff; } @Override public boolean shouldApplyNewJob(Key entityGroup) { // We don't need the entityGroup param but other implementations of the // HighRepJobPolicy interface might. return shouldApply(); } @Override public boolean shouldRollForwardExistingJob(Key entityGroup) { // We don't need the entityGroup param but other implementations of the // HighRepJobPolicy interface might. return shouldApply(); } /* @VisibleForTesting */ int nextRandomInt() { return random.nextInt(RANDOM_CEILING); } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy