Skip to content

Instantly share code, notes, and snippets.

@teffcode
Created April 1, 2025 19:12
Show Gist options
  • Save teffcode/4d715952394fbf68c2f818ca0be1e2fe to your computer and use it in GitHub Desktop.
Save teffcode/4d715952394fbf68c2f818ca0be1e2fe to your computer and use it in GitHub Desktop.
/**
* Line-by-Line Reader Implementation
*
* ## Task
* Implement a line-by-line reader for a large file using the `getObject` function to fetch data in chunks.
* The solution must process the file incrementally without loading it entirely into memory.
*
* ## Functionality Requirements
* - **Method:** Implement a `next()` method that:
* - Returns the next complete line as a string.
* - Returns `null` when no more lines remain.
* - **Chunk Handling:** Use `getObject(s3Path, offsetChar, numChars)` to read chunks of data.
* - You decide how to manage `offsetChar` and `numChars`.
*
* ## Provided Information
* - **getObject(s3Path, offsetChar, numChars):**
* - Fetches up to `numChars` characters from the file starting at `offsetChar`.
* - Returns an empty string or `null` when no more data is available.
*
* ## Constraints
* - Process the file incrementally without loading it entirely into memory.
* - Assume lines are separated by a single newline character (`\n`).
*
* ## Deliverables
* - A working implementation of `next()` (or an equivalent mechanism) that meets the requirements.
* - The solution should be robust, handling edge cases effectively.
* - Be prepared to discuss design decisions and testing approaches.
*
* **Good luck!** 🚀
*/
function getObject(s3Path, offsetChar, numChars) {
const simulatedData = `
{"type": "click", "on": "#subscribeBtn", "time": 167890123}
{"type": "click", "on": "#cancelOrderBtn", "time": 167890456}
{"type": "hover", "on": "#promoBanner", "time": 167891000}
{"type": "scroll", "on": "#productGallery", "time": 167891234}
{"type": "keypress", "on": "#feedbackInput", "time": 167891567}
{"type": "focus", "on": "#emailField", "time": 167891890}
`.trim();
const result = simulatedData.slice(offsetChar, offsetChar + numChars);
return result.length > 0 ? result : null;
}
class S3LineReader {
constructor(s3Path, chunkSize = 20) {
this.s3Path = s3Path;
this.chunkSize = chunkSize;
this.offset = 0;
this.buffer = "";
this.eof = false;
}
next() {
if (this.eof && this.buffer.length === 0) {
return null;
}
while (!this.buffer.includes("\n") && !this.eof) {
const chunk = getObject(this.s3Path, this.offset, this.chunkSize);
if (!chunk) {
this.eof = true;
break;
}
this.buffer += chunk;
this.offset += chunk.length;
}
if (this.buffer.includes("\n")) {
const [line, ...rest] = this.buffer.split("\n");
this.buffer = rest.join("\n");
return line.trim();
}
if (this.eof) {
const line = this.buffer.trim();
this.buffer = "";
return line || null;
}
return null;
}
}
// Example Usage:
const reader = new S3LineReader('s3://mybucket/event_log');
let line;
while ((line = reader.next()) !== null) {
console.log(line);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment