Skip to content
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

Parse path name lines live and festoon callbacks with error handling #473

Merged
merged 6 commits into from
Feb 11, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 6 additions & 7 deletions scripts/prepare_vg.sh
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,10 @@ fi
echo "${1}"
echo "${1%.vg}"

if [[ -e "${1%.vg}.vcf.gz" && -e "${1%.vg}.vcf.gz.tbi" ]]
then
echo "Generating xg index and gbwt index from vg file and VCF"
vg index "${1}" -v "${1%.vg}.vcf.gz" -x "${1}.xg" --gbwt-name "${1}.gbwt"
else
echo "Generating xg index from vg file"
vg index "${1}" -x "${1}.xg"
echo "Generating xg index ${1}.xg from vg file"
vg convert "${1}" -x >"${1}.xg"

if [[ -e "${1%.vg}.vcf.gz" && -e "${1%.vg}.vcf.gz.tbi" ]] ; then
echo "Generating gbwt index ${1}.gbwt from vg file and VCF"
vg gbwt -x "${1}" -v "${1%.vg}.vcf.gz" -o "${1}.gbwt"
fi
38 changes: 38 additions & 0 deletions src/errors.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
/// errors.mjs: Error type definitions for the tube map server

// We can throw this error to trigger our error handling code instead of
// Express's default. It covers input validation failures, and vaguely-expected
// server-side errors we want to report in a controlled way (because they could
// be caused by bad user input to vg).
export class TubeMapError extends Error {
constructor(message) {
super(message);
}
}

// We can throw this error to make Express respond with a bad request error
// message. We should throw it whenever we detect that user input is
// unacceptable.
export class BadRequestError extends TubeMapError {
constructor(message) {
super(message);
this.status = 400;
}
}

// We can throw this error to make Express respond with an internal server
// error message
export class InternalServerError extends TubeMapError {
constructor(message) {
super(message);
this.status = 500;
}
}

// We can throw this error to make Express respond with an internal server
// error message about vg.
export class VgExecutionError extends InternalServerError {
constructor(message) {
super(message);
}
}
62 changes: 62 additions & 0 deletions src/scripts.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
// Tests for data imp[ort scripts, to make sure vg still supports them.

import "./config-server.mjs";

import { find_vg } from "./vg.mjs";

import { mkdtemp, rm, cp, open, access } from 'node:fs/promises';
import { join } from 'node:path';
import { tmpdir } from 'node:os';
import child_process from 'node:child_process';
import { promisify } from 'node:util';

// This runs a command string and returns a promise for {stdout, stderr} that
// rejects if the command fails.
const exec = promisify(child_process.exec);

// This takes a command file and an array of arguments and returns a promise
// for {stdout, stderr} that rejects if the command fails.
const execFile = promisify(child_process.execFile);

const EXAMPLE_DATA = join(__dirname, "..", "exampleData");
const SCRIPTS = join(__dirname, "..", "scripts");

// We set this to a fresh empty directory for each test.
let workDir = null;

beforeEach(async () => {
// Each test gets a fresh directory
workDir = await mkdtemp(join(tmpdir(), 'test-'));
});

afterEach(async () => {
if (workDir) {
rm(workDir, {force: true, recursive: true});
}
});

it("can run prepare_vg.sh", async () => {
for (let filename of ["x.fa", "x.vcf.gz", "x.vcf.gz.tbi"]) {
// Get all the input data
await cp(join(EXAMPLE_DATA, filename), join(workDir, filename));
}

// Build the graph
const vgBuffer = (await execFile(find_vg(), ["construct", "-r", join(workDir, "x.fa"), "-v", join(workDir, "x.vcf.gz"), "-a"], {encoding: "buffer"})).stdout
const graphPath = join(workDir, "x.vg");
console.log("Save graph to " + graphPath);
let file = await open(graphPath, "w");
await file.writeFile(vgBuffer);
await file.close();

// Do the call under test
// We can't use expect here because await expect(...).resolves doesn't actually detect rejections.
console.log("Call script");
let {stdout, stderr} = await execFile(join(SCRIPTS, "prepare_vg.sh"), [join(workDir, "x.vg")]);
console.log("stdout:", stdout);
console.log("stderr:", stderr);
await access(join(workDir, "x.vg.xg"));
await access(join(workDir, "x.vg.gbwt"));
});


Loading