-
Notifications
You must be signed in to change notification settings - Fork 100
Expand file tree
/
Copy pathfunction.js
More file actions
147 lines (125 loc) · 4.27 KB
/
function.js
File metadata and controls
147 lines (125 loc) · 4.27 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
const fs = require('fs');
const path = require('path');
const zlib = require('zlib');
const { v4: uuidv4 } = require('uuid');
const storage = require('./storage');
let storage_handler = new storage.storage();
/**
* Calculate total size of a directory recursively
* @param {string} directory - Path to directory
* @returns {number} Total size in bytes
*/
function parseDirectory(directory) {
let size = 0;
function walkDir(dir) {
const files = fs.readdirSync(dir);
for (const file of files) {
const filepath = path.join(dir, file);
const stat = fs.statSync(filepath);
if (stat.isDirectory()) {
walkDir(filepath);
} else {
size += stat.size;
}
}
}
walkDir(directory);
return size;
}
/**
* Create a simple tar.gz archive from a directory using native zlib
* This creates a gzip-compressed tar archive without external dependencies
* @param {string} sourceDir - Directory to compress
* @param {string} outputPath - Path for the output archive file
* @returns {Promise<void>}
*/
async function createTarGzArchive(sourceDir, outputPath) {
// Create a simple tar-like format (concatenated files with headers)
const files = [];
function collectFiles(dir, baseDir = '') {
const entries = fs.readdirSync(dir);
for (const entry of entries) {
const fullPath = path.join(dir, entry);
const relativePath = path.join(baseDir, entry);
const stat = fs.statSync(fullPath);
if (stat.isDirectory()) {
collectFiles(fullPath, relativePath);
} else {
files.push({
path: relativePath,
fullPath: fullPath,
size: stat.size
});
}
}
}
collectFiles(sourceDir);
// Create a concatenated buffer of all files with simple headers
const chunks = [];
for (const file of files) {
const content = fs.readFileSync(file.fullPath);
// Simple header: filename length (4 bytes) + filename + content length (4 bytes) + content
const pathBuffer = Buffer.from(file.path);
const pathLengthBuffer = Buffer.allocUnsafe(4);
pathLengthBuffer.writeUInt32BE(pathBuffer.length, 0);
const contentLengthBuffer = Buffer.allocUnsafe(4);
contentLengthBuffer.writeUInt32BE(content.length, 0);
chunks.push(pathLengthBuffer);
chunks.push(pathBuffer);
chunks.push(contentLengthBuffer);
chunks.push(content);
}
const combined = Buffer.concat(chunks);
// Compress using gzip
const compressed = zlib.gzipSync(combined, { level: 9 });
fs.writeFileSync(outputPath, compressed);
}
exports.handler = async function(event) {
const bucket = event.bucket.bucket;
const input_prefix = event.bucket.input;
const output_prefix = event.bucket.output;
const key = event.object.key;
// Create unique download path
const download_path = path.join('/tmp', `${key}-${uuidv4()}`);
fs.mkdirSync(download_path, { recursive: true });
// Download directory from storage
const s3_download_begin = Date.now();
await storage_handler.download_directory(bucket, path.join(input_prefix, key), download_path);
const s3_download_stop = Date.now();
// Calculate size of downloaded files
const size = parseDirectory(download_path);
// Compress directory
const compress_begin = Date.now();
const archive_name = `${key}.tar.gz`;
const archive_path = path.join(download_path, archive_name);
await createTarGzArchive(download_path, archive_path);
const compress_end = Date.now();
// Get archive size
const archive_size = fs.statSync(archive_path).size;
// Upload compressed archive
const s3_upload_begin = Date.now();
const [key_name, uploadPromise] = storage_handler.upload(
bucket,
path.join(output_prefix, archive_name),
archive_path
);
await uploadPromise;
const s3_upload_stop = Date.now();
// Calculate times in microseconds
const download_time = (s3_download_stop - s3_download_begin) * 1000;
const upload_time = (s3_upload_stop - s3_upload_begin) * 1000;
const process_time = (compress_end - compress_begin) * 1000;
return {
result: {
bucket: bucket,
key: key_name
},
measurement: {
download_time: download_time,
download_size: size,
upload_time: upload_time,
upload_size: archive_size,
compute_time: process_time
}
};
};