diff --git a/swh/scheduler/backend.py b/swh/scheduler/backend.py --- a/swh/scheduler/backend.py +++ b/swh/scheduler/backend.py @@ -221,11 +221,11 @@ for this task type """ + keys = [key for key in self.task_type_keys if key in task_type] query = self._format_query( """insert into task_type ({keys}) values ({placeholders})""", - self.task_type_keys, - ) - cursor.execute(query, [task_type[key] for key in self.task_type_keys]) + keys) + cursor.execute(query, keys) @autocommit def get_task_type(self, task_type_name, cursor=None): diff --git a/swh/scheduler/cli.py b/swh/scheduler/cli.py --- a/swh/scheduler/cli.py +++ b/swh/scheduler/cli.py @@ -70,15 +70,6 @@ return ''.join(lines) -def list_task_types(ctx, param, value): - if not value or ctx.resilient_parsing: - return - click.echo("Known task types:") - for tasktype in ctx.obj['scheduler'].get_task_types(): - click.echo('{type}:\n {description}'.format(**tasktype)) - ctx.exit() - - @click.group(context_settings=CONTEXT_SETTINGS) @click.option('--cls', '-c', default='local', type=click.Choice(['local', 'remote']), @@ -124,8 +115,6 @@ @cli.group('task') -@click.option('--list-types', '-l', is_flag=True, default=False, is_eager=True, - expose_value=False, callback=list_task_types) @click.pass_context def task(ctx): """Manipulate tasks.""" @@ -461,5 +450,77 @@ app.run(host, port=port, debug=bool(debug)) +@cli.group('task-type') +@click.pass_context +def task_type(ctx): + """Manipulate task types.""" + pass + + +@task_type.command('list') +@click.option('--verbose', '-v', is_flag=True, default=False) +@click.option('--task_type', '-t', multiple=True, default=None, + help='List task types of given type') +@click.option('--task_name', '-n', multiple=True, default=None, + help='List task types of given backend task name') +@click.pass_context +def list_task_types(ctx, verbose, task_type, task_name): + click.echo("Known task types:") + if verbose: + tmpl = click.style('{type}: ', bold=True) + '''{backend_name} + {description} + interval: {default_interval} [{min_interval}, {max_interval}] + backoff_factor: {backoff_factor} + max_queue_length: {max_queue_length} + num_retries: {num_retries} + retry_delay: {retry_delay} +''' + else: + tmpl = '{type}:\n {description}' + for tasktype in ctx.obj['scheduler'].get_task_types(): + if task_type and tasktype['type'] not in task_type: + continue + if task_name and tasktype['backend_name'] not in task_name: + continue + click.echo(tmpl.format(**tasktype)) + + +@task_type.command('add') +@click.argument('type', required=1) +@click.argument('task-name', required=1) +@click.argument('description', required=1) +@click.option('--default-interval', '-i', default='90 days', + help='Default interval ("90 days" by default)') +@click.option('--min-interval', default=None, + help='Minimum interval (default interval if not set)') +@click.option('--max-interval', '-i', default=None, + help='Maximal interval (default interval if not set)') +@click.option('--backoff-factor', '-f', type=float, default=1, + help='Backoff factor') +@click.pass_context +def add_task_type(ctx, type, task_name, description, + default_interval, min_interval, max_interval, + backoff_factor): + """Create a new task type + """ + scheduler = ctx.obj['scheduler'] + if not scheduler: + raise ValueError('Scheduler class (local/remote) must be instantiated') + task_type = dict( + type=type, + backend_name=task_name, + description=description, + default_interval=default_interval, + min_interval=min_interval, + max_interval=max_interval, + backoff_factor=backoff_factor, + max_queue_length=None, + num_retries=None, + retry_delay=None, + ) + scheduler.create_task_type(task_type) + click.echo('OK') + + if __name__ == '__main__': cli()