Decorator that creates AFF4 and RELDB cronjobs from a given mixin.

def DualDBSystemCronJob(legacy_name=None, stateful=False):
  """Decorator that creates AFF4 and RELDB cronjobs from a given mixin."""

  def Decorator(cls):
    """Decorator producing 2 classes: legacy style one and a new style one."""
    if not legacy_name:
      raise ValueError("legacy_name has to be provided")

    # Legacy cron jobs have different base classes depending on whether they're
    # stateful or not.
    if stateful:
      aff4_base_cls = StatefulSystemCronFlow
    else:
      aff4_base_cls = SystemCronFlow

    # Make sure that we're dealing with a true mixin to avoid subtle errors.
    if issubclass(cls, cronjobs.SystemCronJobBase):
      raise ValueError("Mixin class shouldn't inherit from SystemCronJobBase")

    if issubclass(cls, aff4_base_cls):
      raise ValueError("Mixin class shouldn't inherit from %s" %
                       aff4_base_cls.__name__)

    # Generate legacy class. Register it within the module as it's not going
    # to be returned from the decorator.
    aff4_cls = compatibility.MakeType(
        legacy_name, (cls, LegacyCronJobAdapterMixin, aff4_base_cls), {})
    module = sys.modules[cls.__module__]
    setattr(module, legacy_name, aff4_cls)

    # Generate new class. No need to register it in the module (like the legacy
    # one) since it will replace the original decorated class.
    reldb_cls = compatibility.MakeType(
        compatibility.GetName(cls), (cls, cronjobs.SystemCronJobBase), {})
    return reldb_cls

  return Decorator