Skip to content

Commit

Permalink
feat: parallel downloads
Browse files Browse the repository at this point in the history
  • Loading branch information
jedwards1230 committed Apr 21, 2024
1 parent 24a75d7 commit 805b9d0
Show file tree
Hide file tree
Showing 6 changed files with 56 additions and 28 deletions.
11 changes: 10 additions & 1 deletion docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,20 @@ services:
build:
context: .
dockerfile: Dockerfile
develop:
watch:
- action: sync
path: ./src
target: /app/src/
ignore:
- node_modules/
- action: rebuild
path: package.json
volumes:
- data:/app/data/
- ${PWD}/downloads:/app/downloads/
env_file:
- .env

volumes:
data:
data:
4 changes: 3 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,9 @@
},
"scripts": {
"start": "bun run cli.ts",
"build": "bun build ./cli.ts --compile --minify --sourcemap --outfile libro"
"build:cli": "bun build ./cli.ts --compile --minify --sourcemap --outfile libro",
"build:docker": "docker build . -t jedwards1230/libro:latest",
"push:docker": "docker push jedwards1230/libro:latest"
},
"devDependencies": {
"@types/bun": "latest",
Expand Down
48 changes: 32 additions & 16 deletions service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,40 +27,46 @@ const scanLibrary = async () => {
let overwrite = false;
let keepZip = false;
const downloadBooks = async (newBooks: Audiobook[]) => {
const isbns = newBooks.map((book: any) => book.isbn);
const isbns = newBooks.map((book) => book.isbn);
console.log("Downloading new books...");

const audiobookLibrary = await client.getLibrary();

let count = 0;
for (const isbn of isbns) {
const promisedBooks = isbns.map(async (isbn) => {
console.log(`Searching library for ISBN: ${isbn}`);
const book = audiobookLibrary[isbn];
if (book) {
console.log(`Downloading: ${book.title}`);
const [path, zippedPaths] = await client.downloadBook(
book,
overwrite,
keepZip
);
if (path) {
console.log(`Downloaded ${book.title}`);
count++;
} else {
console.log("No new books downloaded");
try {
const [path, zippedPaths] = await client.downloadBook(
book,
overwrite,
keepZip
);
if (path) {
console.log(`Downloaded ${book.title}`);
return book;
} else {
console.log("No new books downloaded");
}
} catch (error) {
console.error("An error occurred:", error);
}
} else {
console.log(`No book found with ISBN: ${isbn}`);
console.warn(`No book found with ISBN: ${isbn}`);
}
}
});

const books = await Promise.all(promisedBooks);
const count = books.filter((book) => book).length;

console.log(`Downloaded ${count} new books.`);
};

let isRunning = false;
const runService = async () => {
if (isRunning) {
console.log("Service is already running. Skipping this iteration.");
//console.debug("Service is already running. Skipping this iteration.");
return;
}

Expand All @@ -78,3 +84,13 @@ const runService = async () => {

runService();
setInterval(runService, 30000);

process.on("SIGINT", () => {
console.log("Exiting...");
process.exit(0);
});

process.on("unhandledRejection", (error) => {
console.error("An unhandled rejection occurred:", error);
process.exit(1);
});
2 changes: 1 addition & 1 deletion src/LibroFmClient.ts
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,7 @@ export default class LibroFmClient {
}

try {
const bookPath = `${book.authors}-${book.title}`;
const bookPath = `${book.authors}`;
const [path, zipped_files] = await DownloadCLient.downloadFiles(
bookPath,
urls,
Expand Down
5 changes: 3 additions & 2 deletions src/lib/Directories.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,12 @@ const DOWNLOAD_DIR = path.join(PROJECT_DIR, "downloads");

// App data
const APP_DIR = path.join(PROJECT_DIR, "data");
const CACHE_DIR = path.join(APP_DIR, "cache");
const LOGS_DIR = path.join(APP_DIR, "logs");
const CONFIG_DIR = path.join(APP_DIR, "config");

// Create directories if they don't exist
const dirs = [APP_DIR, LOGS_DIR, DOWNLOAD_DIR, CONFIG_DIR];
const dirs = [APP_DIR, LOGS_DIR, CACHE_DIR, DOWNLOAD_DIR, CONFIG_DIR];
for (const dir of dirs) {
if (!fs.existsSync(dir)) {
fs.mkdirSync(dir);
Expand All @@ -22,4 +23,4 @@ for (const dir of dirs) {
const STATE_PATH = `${CONFIG_DIR}/state.json`;
const CONFIG_PATH = `${CONFIG_DIR}/config.json`;

export { LOGS_DIR, DOWNLOAD_DIR, STATE_PATH, CONFIG_PATH };
export { LOGS_DIR, CACHE_DIR, DOWNLOAD_DIR, STATE_PATH, CONFIG_PATH };
14 changes: 7 additions & 7 deletions src/lib/DownloadClient.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import JSZip from "jszip";

import APIHandler from "../APIHandler";
import logger, { LogMethod } from "./Logger";
import { DOWNLOAD_DIR } from "./Directories";
import { CACHE_DIR, DOWNLOAD_DIR } from "./Directories";

const scope = "DownloadClient";

Expand All @@ -17,7 +17,7 @@ export default class DownloadCLient {
* */
@LogMethod({ scope, message: "Downloading files..." })
static async downloadFiles(
bookPath: string,
filenamePrefix: string,
urls: string[],
authToken: string,
keepZip = false
Expand All @@ -29,17 +29,17 @@ export default class DownloadCLient {
keepZip &&
(await Promise.all(
buffers.map((buffer, idx) =>
DownloadCLient.save(buffer, `/${bookPath}-${idx}.zip`)
DownloadCLient.save(buffer, `/${filenamePrefix}-${idx}.zip`)
)
));

const paths = await Promise.all(
buffers.map((buffer, idx) =>
DownloadCLient.unzip(buffer, `/${bookPath}-${idx}`)
DownloadCLient.unzip(buffer, `/${filenamePrefix}-${idx}`)
)
);

const finalPath = path.join(DOWNLOAD_DIR, bookPath);
const finalPath = path.join(DOWNLOAD_DIR, filenamePrefix);
await DownloadCLient.mergeDirectories(paths, finalPath);

return [finalPath, zipped_files];
Expand Down Expand Up @@ -69,7 +69,7 @@ export default class DownloadCLient {
static async save(buffer: ArrayBuffer, filename: string): Promise<string> {
const data = new Uint8Array(buffer);
try {
const outputPath = path.join(DOWNLOAD_DIR, filename);
const outputPath = path.join(CACHE_DIR, filename);
fs.writeFileSync(outputPath, data);
return outputPath;
} catch (error) {
Expand All @@ -88,7 +88,7 @@ export default class DownloadCLient {
const zip = new JSZip();

const directory = await zip.loadAsync(buffer);
const outputPath = path.join(DOWNLOAD_DIR, outputDir);
const outputPath = path.join(CACHE_DIR, outputDir);

if (!fs.existsSync(outputPath)) {
fs.mkdirSync(outputPath);
Expand Down

0 comments on commit 805b9d0

Please sign in to comment.