Example #1
0
def test_package_specs(auth_client, db, config, work_manager, package_version,
                       spec, n_tasks):

    response = auth_client.post(
        "/api/jobs",
        json={
            "items_spec": spec,
            "manifest": "quetz-transmutation:transmutation"
        },
    )

    assert response.status_code == 201
    run_jobs(db)
    run_tasks(db, work_manager)

    check_status(db)

    n_created_task = db.query(Task).count()

    assert n_created_task == n_tasks

    # cleanup
    try:
        db.query(PackageVersion).delete()
        db.query(Job).delete()
        db.query(Task).delete()
    finally:
        db.commit()
Example #2
0
async def test_running_task(db, user, package_version, manager):

    func_serialized = pickle.dumps(long_running)
    job = Job(owner_id=user.id, manifest=func_serialized, items_spec="*")
    db.add(job)
    db.commit()
    run_jobs(db)
    processes = run_tasks(db, manager)
    db.refresh(job)
    task = db.query(Task).one()

    assert job.status == JobStatus.running

    assert task.status == TaskStatus.pending

    time.sleep(0.01)
    check_status(db)

    db.refresh(task)
    assert task.status == TaskStatus.running

    # wait for job to finish
    await processes[0].wait()

    check_status(db)

    db.refresh(task)
    assert task.status == TaskStatus.success
Example #3
0
async def test_create_job(db, user, package_version, manager):

    func_serialized = pickle.dumps(func)
    job = Job(owner_id=user.id, manifest=func_serialized, items_spec="*")
    db.add(job)
    db.commit()
    run_jobs(db)
    new_jobs = run_tasks(db, manager)
    db.refresh(job)
    task = db.query(Task).one()

    assert job.status == JobStatus.running

    assert task.status == TaskStatus.pending

    # wait for job to finish
    await new_jobs[0].wait()

    check_status(db)

    db.refresh(task)
    assert task.status == TaskStatus.success
    assert os.path.isfile("test-output.txt")

    db.refresh(job)
    assert job.status == JobStatus.success
Example #4
0
async def test_harvest_endpoint_and_job(
    auth_client, db, config, work_manager, package_version, app, channel_name
):

    async with AsyncClient(app=app, base_url="http://test") as ac:
        response = await ac.put("/api/harvester", json={"package_spec": "*"})

    assert response.status_code == 200
    run_jobs(db)
    new_jobs = run_tasks(db, work_manager)
    await new_jobs[0].wait()

    check_status(db)

    task = db.query(Task).one()
    db.refresh(task)
    assert task.status == TaskStatus.success

    pkgstore = config.get_package_store()
    fileh = pkgstore.serve_path(
        channel_name,
        Path("metadata")
        / package_version.platform
        / package_version.filename.replace(".tar.bz2", ".json"),
    )
    ok_ = fileh.read(10)
    assert ok_

    # cleanup
    try:
        db.query(PackageVersion).delete()
        db.query(Job).delete()
        db.query(Task).delete()
    finally:
        db.commit()
Example #5
0
def test_filter_versions(db, user, package_version, spec, n_tasks, manager):

    func_serialized = pickle.dumps(func)
    job = Job(
        owner_id=user.id,
        manifest=func_serialized,
        items_spec=spec,
    )
    db.add(job)
    db.commit()
    run_jobs(db)
    run_tasks(db, manager)
    db.refresh(job)
    n_created_tasks = db.query(Task).count()

    assert n_created_tasks == n_tasks
Example #6
0
def test_empty_package_spec(db, user, package_version, caplog, items_spec):

    func_serialized = pickle.dumps(func)
    job = Job(owner_id=user.id,
              manifest=func_serialized,
              items_spec=items_spec)
    db.add(job)
    db.commit()
    run_jobs(db)
    db.refresh(job)
    task = db.query(Task).one_or_none()

    assert "empty" in caplog.text
    assert "skipping" in caplog.text
    assert job.status == JobStatus.success
    assert task is None
Example #7
0
async def test_transmutation_endpoint(api_key, db, config, work_manager,
                                      package_version, app, channel_name):

    # we need to use asynchronous http client because the test is async
    async with AsyncClient(app=app, base_url="http://test") as ac:
        response = await ac.post(
            "/api/jobs",
            json={
                "items_spec": "*",
                "manifest": "quetz-transmutation:transmutation"
            },
            headers={"x-api-key": api_key.key},
        )

    assert response.status_code == 201
    run_jobs(db)
    new_jobs = run_tasks(db, work_manager)
    await new_jobs[0].wait()

    check_status(db)

    task = db.query(Task).one()
    db.refresh(task)
    assert task.status == TaskStatus.success

    pkgstore = config.get_package_store()
    fileh = pkgstore.serve_path(
        channel_name,
        Path(package_version.platform) /
        package_version.filename.replace(".tar.bz2", ".conda"),
    )
    ok_ = fileh.read(10)
    assert ok_

    conda_version = (db.query(PackageVersion).filter(
        PackageVersion.package_format == 'conda').one_or_none())

    assert conda_version

    # cleanup
    try:
        db.query(PackageVersion).delete()
        db.query(Job).delete()
        db.query(Task).delete()
    finally:
        db.commit()
Example #8
0
async def test_failed_task(db, user, package_version, manager):

    func_serialized = pickle.dumps(failed_func)
    job = Job(owner_id=user.id, manifest=func_serialized, items_spec="*")
    db.add(job)
    db.commit()
    run_jobs(db)
    new_jobs = run_tasks(db, manager)
    task = db.query(Task).one()
    with pytest.raises(Exception, match="some exception"):
        await new_jobs[0].wait()

    check_status(db)

    db.refresh(task)
    assert task.status == TaskStatus.failed

    db.refresh(job)
    assert job.status == JobStatus.success
Example #9
0
async def test_restart_worker_process(db, user, package_version, manager,
                                      caplog):
    # test if we can resume jobs if a worker was killed/restarted
    func_serialized = pickle.dumps(long_running)

    job = Job(owner_id=user.id, manifest=func_serialized, items_spec="*")
    db.add(job)
    db.commit()
    run_jobs(db)
    run_tasks(db, manager)
    db.refresh(job)
    task = db.query(Task).one()

    assert job.status == JobStatus.running

    assert task.status == TaskStatus.pending

    time.sleep(0.01)
    check_status(db)

    db.refresh(task)
    assert task.status == TaskStatus.running

    _process_cache.clear()

    check_status(db)
    assert task.status == TaskStatus.created
    assert "lost" in caplog.text

    new_processes = run_tasks(db, manager)
    db.refresh(task)

    assert len(new_processes) == 1
    assert task.status == TaskStatus.pending

    more_processes = run_tasks(db, manager)
    await new_processes[0].wait()
    even_more_processes = run_tasks(db, manager)
    check_status(db)
    db.refresh(task)
    assert not more_processes
    assert not even_more_processes
    assert task.status == TaskStatus.success
Example #10
0
async def test_run_tasks_only_on_new_versions(db, user, package_version,
                                              manager, dao, channel_name,
                                              package_name):

    func_serialized = pickle.dumps(dummy_func)
    job = Job(owner_id=user.id, manifest=func_serialized, items_spec="*")
    db.add(job)
    db.commit()
    run_jobs(db)
    new_jobs = run_tasks(db, manager)
    db.refresh(job)
    task = db.query(Task).one()

    await new_jobs[0].wait()
    check_status(db)
    db.refresh(task)
    db.refresh(job)
    assert task.status == TaskStatus.success
    assert job.status == JobStatus.success

    job.status = JobStatus.pending
    db.commit()
    run_jobs(db)
    new_jobs = run_tasks(db, manager)
    check_status(db)
    db.refresh(job)
    assert not new_jobs
    assert job.status == JobStatus.success

    filename = "test-package-0.2-0.tar.bz2"
    add_package_version(filename, "0.2", channel_name, user, dao, package_name)

    job.status = JobStatus.pending
    db.commit()
    run_jobs(db)
    new_jobs = run_tasks(db, manager)
    assert len(new_jobs) == 1
    assert job.status == JobStatus.running
    assert len(job.tasks) == 2
    assert job.tasks[0].status == TaskStatus.success
    assert job.tasks[1].status == TaskStatus.pending

    # force rerunning
    job.status = JobStatus.pending
    run_jobs(db, force=True)
    db.refresh(job)
    new_jobs = run_tasks(db, manager)
    assert len(job.tasks) == 4
    assert len(new_jobs) == 2
Example #11
0
File: cli.py Project: beenje/quetz
def watch_job_queue(
    path: str = typer.Argument(None, help="Path to the plugin folder"),
    num_procs: Optional[int] = typer.Option(
        None, help="Number of processes to use. Default: number of CPU cores"),
) -> None:
    import time

    configure_logger(loggers=("quetz", ))

    from quetz.jobs.runner import check_status, run_jobs, run_tasks
    from quetz.tasks.workers import SubprocessWorker

    config = _get_config(path)
    manager = SubprocessWorker("", {}, config, {'max_workers': num_procs})
    with working_directory(path):
        db = get_session(config.sqlalchemy_database_url)
        try:
            while True:
                run_jobs(db)
                run_tasks(db, manager)
                check_status(db)
                time.sleep(5)
        except KeyboardInterrupt:
            db.close()
Example #12
0
def test_refresh_job(auth_client, user, db, package_version, manager):

    func_serialized = pickle.dumps(dummy_func)
    job = Job(
        owner_id=user.id,
        manifest=func_serialized,
        items_spec="*",
        status=JobStatus.success,
    )
    task = Task(job=job,
                status=TaskStatus.success,
                package_version=package_version)
    db.add(job)
    db.add(task)
    db.commit()

    assert job.status == JobStatus.success
    assert len(job.tasks) == 1

    response = auth_client.patch(f"/api/jobs/{job.id}",
                                 json={"status": "pending"})

    assert response.status_code == 200

    db.refresh(job)
    assert job.status == JobStatus.pending
    assert len(job.tasks) == 1

    run_jobs(db)
    assert job.status == JobStatus.success
    assert len(job.tasks) == 1

    response = auth_client.patch(f"/api/jobs/{job.id}",
                                 json={
                                     "status": "pending",
                                     "force": True
                                 })
    db.refresh(job)
    assert job.status == JobStatus.running
    assert len(job.tasks) == 2

    # forcing one job should not affect the other
    other_job = Job(
        id=2,
        owner_id=user.id,
        manifest=func_serialized,
        items_spec="*",
        status=JobStatus.success,
    )
    job.status = JobStatus.pending
    db.add(other_job)
    db.commit()

    response = auth_client.patch(f"/api/jobs/{other_job.id}",
                                 json={
                                     "status": "pending",
                                     "force": True
                                 })
    db.refresh(job)
    assert job.status == JobStatus.pending
    assert len(job.tasks) == 2