1818 */
1919
2020const putility = require ( '@heyputer/putility' ) ;
21- const { MultiDetachable } = putility . libs . listener ;
22- const { TDetachable } = putility . traits ;
23- const { NodeInternalIDSelector, NodeChildSelector, NodeUIDSelector } = require ( '../../../filesystem/node/selectors' ) ;
2421const { Context } = require ( '../../../util/context' ) ;
2522const fsCapabilities = require ( '../../../filesystem/definitions/capabilities' ) ;
26- const { UploadProgressTracker } = require ( '../../../filesystem/storage/UploadProgressTracker' ) ;
27- const FSNodeContext = require ( '../../../filesystem/FSNodeContext' ) ;
28- const { RESOURCE_STATUS_PENDING_CREATE } = require ( '../ResourceService' ) ;
29- const { ParallelTasks } = require ( '../../../util/otelutil' ) ;
30- const { TYPE_DIRECTORY } = require ( '../../../filesystem/FSNodeContext' ) ;
31- const APIError = require ( '../../../api/APIError' ) ;
32- const { MODE_WRITE } = require ( '../../../services/fs/FSLockService' ) ;
33- const { DB_WRITE } = require ( '../../../services/database/consts' ) ;
34- const { stuck_detector_stream, hashing_stream } = require ( '../../../util/streamutil' ) ;
35- const crypto = require ( 'crypto' ) ;
36- const { OperationFrame } = require ( '../../../services/OperationTraceService' ) ;
37- const path = require ( 'path' ) ;
38- const uuidv4 = require ( 'uuid' ) . v4 ;
3923const config = require ( '../../../config.js' ) ;
40- const { Actor } = require ( '../../../services/auth/Actor.js' ) ;
41- const { UserActorType } = require ( '../../../services/auth/Actor.js' ) ;
42- const { get_user } = require ( '../../../helpers.js' ) ;
43-
44- const STUCK_STATUS_TIMEOUT = 10 * 1000 ;
45- const STUCK_ALARM_TIMEOUT = 20 * 1000 ;
4624
4725class PuterFSProvider extends putility . AdvancedBase {
4826
49- get #services ( ) { // we really should just pass services in constructor, global state is a bit messy
50- return Context . get ( 'services' ) ;
51- }
52-
53- /** @type {import('../../../services/MeteringService/MeteringService.js').MeteringService } */
54- get #meteringService ( ) {
55- return this . #services. get ( 'meteringService' ) . meteringService ;
56- }
57-
5827 constructor ( ...a ) {
5928 super ( ...a ) ;
6029 this . log_fsentriesNotFound = ( config . logging ?? [ ] )
@@ -86,44 +55,37 @@ class PuterFSProvider extends putility.AdvancedBase {
8655 * @param {NodeSelector } param.selector - The selector used for checking.
8756 * @returns {Promise<boolean> } - True if the node exists, false otherwise.
8857 */
89- async quick_check ( {
90- selector,
91- } ) {
58+ async quick_check ( ) {
9259 console . error ( 'This .quick_check should not be called!' ) ;
9360 throw new Error ( 'This .quick_check should not be called!' ) ;
9461 }
9562
96- async stat ( {
97- selector,
98- options,
99- controls,
100- node,
101- } ) {
63+ async stat ( ) {
10264 console . error ( 'This .stat should not be called!' ) ;
10365 throw new Error ( 'This .stat should not be called!' ) ;
10466 }
10567
106- async readdir ( { node } ) {
68+ async readdir ( ) {
10769 console . error ( 'This .readdir should not be called!' ) ;
10870 throw new Error ( 'This .readdir should not be called!' ) ;
10971 }
11072
111- async move ( { context , node , new_parent , new_name , metadata } ) {
73+ async move ( ) {
11274 console . error ( 'This .move should not be called!' ) ;
11375 throw new Error ( 'This .move should not be called!' ) ;
11476 }
11577
116- async copy_tree ( { context , node , options = { } } ) {
78+ async copy_tree ( ) {
11779 console . error ( 'This .copy_tree should not be called!' ) ;
11880 throw new Error ( 'This .copy_tree should not be called!' ) ;
11981 }
12082
121- async unlink ( { context , node , options = { } } ) {
83+ async unlink ( ) {
12284 console . error ( 'This .unlink should not be called!' ) ;
12385 throw new Error ( 'This .unlink should not be called!' ) ;
12486 }
12587
126- async rmdir ( { context , node , options = { } } ) {
88+ async rmdir ( ) {
12789 console . error ( 'This .rmdir should not be called!' ) ;
12890 throw new Error ( 'This .rmdir should not be called!' ) ;
12991 }
@@ -138,7 +100,7 @@ class PuterFSProvider extends putility.AdvancedBase {
138100 * @param {boolean } param.immutable
139101 * @returns {Promise<FSNode> }
140102 */
141- async mkdir ( { context , parent , name , immutable } ) {
103+ async mkdir ( ) {
142104 console . error ( 'This .mkdir should not be called!' ) ;
143105 throw new Error ( 'This .mkdir should not be called!' ) ;
144106 }
@@ -188,7 +150,7 @@ class PuterFSProvider extends putility.AdvancedBase {
188150 * @param {File } param.file: The file to write.
189151 * @returns {Promise<FSNode> }
190152 */
191- async write_new ( { context , parent , name , file } ) {
153+ async write_new ( ) {
192154 console . error ( 'This .write_new should not be called!' ) ;
193155 throw new Error ( 'This .write_new should not be called!' ) ;
194156 }
@@ -203,126 +165,12 @@ class PuterFSProvider extends putility.AdvancedBase {
203165 * @param {File } param.file: The file to write.
204166 * @returns {Promise<FSNodeContext> }
205167 */
206- async write_overwrite ( { context , node , file } ) {
168+ async write_overwrite ( ) {
207169 console . error ( 'This .write_overwrite should not be called!' ) ;
208170 throw new Error ( 'This .write_overwrite should not be called!' ) ;
209171 }
210172
211- /**
212- * @param {Object } param
213- * @param {File } param.file: The file to write.
214- * @returns
215- */
216- async #storage_upload ( {
217- uuid,
218- bucket,
219- bucket_region,
220- file,
221- tmp,
222- } ) {
223- const log = this . #services. get ( 'log-service' ) . create ( 'fs.#storage_upload' ) ;
224- const errors = this . #services. get ( 'error-service' ) . create ( log ) ;
225- const svc_event = this . #services. get ( 'event' ) ;
226-
227- const svc_mountpoint = this . #services. get ( 'mountpoint' ) ;
228- const storage = svc_mountpoint . get_storage ( this . constructor . name ) ;
229-
230- bucket ??= config . s3_bucket ;
231- bucket_region ??= config . s3_region ?? config . region ;
232-
233- let upload_tracker = new UploadProgressTracker ( ) ;
234-
235- svc_event . emit ( 'fs.storage.upload-progress' , {
236- upload_tracker,
237- context : Context . get ( ) ,
238- meta : {
239- item_uid : uuid ,
240- item_path : tmp . path ,
241- } ,
242- } ) ;
243-
244- if ( ! file . buffer ) {
245- let stream = file . stream ;
246- let alarm_timeout = null ;
247- stream = stuck_detector_stream ( stream , {
248- timeout : STUCK_STATUS_TIMEOUT ,
249- on_stuck : ( ) => {
250- this . frame . status = OperationFrame . FRAME_STATUS_STUCK ;
251- log . warn ( 'Upload stream stuck might be stuck' , {
252- bucket_region,
253- bucket,
254- uuid,
255- } ) ;
256- alarm_timeout = setTimeout ( ( ) => {
257- errors . report ( 'fs.write.s3-upload' , {
258- message : 'Upload stream stuck for too long' ,
259- alarm : true ,
260- extra : {
261- bucket_region,
262- bucket,
263- uuid,
264- } ,
265- } ) ;
266- } , STUCK_ALARM_TIMEOUT ) ;
267- } ,
268- on_unstuck : ( ) => {
269- clearTimeout ( alarm_timeout ) ;
270- this . frame . status = OperationFrame . FRAME_STATUS_WORKING ;
271- } ,
272- } ) ;
273- file = { ...file , stream } ;
274- }
275-
276- let hashPromise ;
277- if ( file . buffer ) {
278- const hash = crypto . createHash ( 'sha256' ) ;
279- hash . update ( file . buffer ) ;
280- hashPromise = Promise . resolve ( hash . digest ( 'hex' ) ) ;
281- } else {
282- const hs = hashing_stream ( file . stream ) ;
283- file . stream = hs . stream ;
284- hashPromise = hs . hashPromise ;
285- }
286-
287- hashPromise . then ( hash => {
288- const svc_event = this . #services. get ( 'event' ) ;
289- svc_event . emit ( 'outer.fs.write-hash' , {
290- hash, uuid,
291- } ) ;
292- } ) ;
293-
294- const state_upload = storage . create_upload ( ) ;
295-
296- try {
297- await state_upload . run ( {
298- uid : uuid ,
299- file,
300- storage_meta : { bucket, bucket_region } ,
301- storage_api : { progress_tracker : upload_tracker } ,
302- } ) ;
303- } catch ( e ) {
304- errors . report ( 'fs.write.storage-upload' , {
305- source : e || new Error ( 'unknown' ) ,
306- trace : true ,
307- alarm : true ,
308- extra : {
309- bucket_region,
310- bucket,
311- uuid,
312- } ,
313- } ) ;
314- throw APIError . create ( 'upload_failed' ) ;
315- }
316-
317- return state_upload ;
318- }
319-
320- async read ( {
321- context,
322- node,
323- version_id,
324- range,
325- } ) {
173+ async read ( ) {
326174 console . error ( 'This .read should not be called!' ) ;
327175 throw new Error ( 'This .read should not be called!' ) ;
328176 }
0 commit comments