Skip to content

Commit ea3dbcd

Browse files
committed
dev(puterfs): move write_overwrite to extension
1 parent a2cebf8 commit ea3dbcd

File tree

2 files changed

+101
-97
lines changed

2 files changed

+101
-97
lines changed

extensions/puterfs/main.js

Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -621,6 +621,104 @@ class PuterFSProvider {
621621
return node;
622622
}
623623

624+
/**
625+
* Overwrite an existing file. Throws an error if the destination does not
626+
* exist.
627+
*
628+
* @param {Object} param
629+
* @param {Context} param.context
630+
* @param {FSNodeContext} param.node: The node to write to.
631+
* @param {File} param.file: The file to write.
632+
* @returns {Promise<FSNodeContext>}
633+
*/
634+
async write_overwrite ({ context, node, file }) {
635+
const {
636+
tmp, fsentry_tmp, message, actor: inputActor,
637+
} = context.values;
638+
const actor = inputActor ?? Context.get('actor');
639+
640+
if ( ! await svc_acl.check(actor, node, 'write') ) {
641+
throw await svc_acl.get_safe_acl_error(actor, node, 'write');
642+
}
643+
644+
const uid = await node.get('uid');
645+
646+
const bucket_region = node.entry.bucket_region;
647+
const bucket = node.entry.bucket;
648+
649+
const state_upload = await this.#storage_upload({
650+
uuid: node.entry.uuid,
651+
bucket,
652+
bucket_region,
653+
file,
654+
tmp: {
655+
...tmp,
656+
path: await node.get('path'),
657+
},
658+
});
659+
660+
if ( fsentry_tmp?.thumbnail_promise ) {
661+
fsentry_tmp.thumbnail = await fsentry_tmp.thumbnail_promise;
662+
delete fsentry_tmp.thumbnail_promise;
663+
}
664+
665+
const ts = Math.round(Date.now() / 1000);
666+
const raw_fsentry_delta = {
667+
modified: ts,
668+
accessed: ts,
669+
size: file.size,
670+
...fsentry_tmp,
671+
};
672+
673+
svc_resource.register({
674+
uid,
675+
status: RESOURCE_STATUS_PENDING_CREATE,
676+
});
677+
678+
const filesize = file.size;
679+
svc_size.change_usage(actor.type.user.id, filesize);
680+
681+
// Meter ingress
682+
const ownerId = await node.get('user_id');
683+
const ownerActor = new Actor({
684+
type: new UserActorType({
685+
user: await get_user({ id: ownerId }),
686+
}),
687+
});
688+
svc_metering.incrementUsage(ownerActor, 'filesystem:ingress:bytes', filesize);
689+
690+
const entryOp = await svc_fsEntry.update(uid, raw_fsentry_delta);
691+
692+
// depends on fsentry, does not depend on S3
693+
const entryOpPromise = (async () => {
694+
await entryOp.awaitDone();
695+
svc_resource.free(uid);
696+
})();
697+
698+
const cachePromise = (async () => {
699+
await svc_fileCache.invalidate(node);
700+
})();
701+
702+
(async () => {
703+
await Promise.all([entryOpPromise, cachePromise]);
704+
svc_event.emit('fs.write.file', {
705+
node,
706+
context,
707+
});
708+
})();
709+
710+
// TODO (xiaochen): determine if this can be removed, post_insert handler need
711+
// to skip events from other servers (why? 1. current write logic is inside
712+
// the local server 2. broadcast system conduct "fire-and-forget" behavior)
713+
state_upload.post_insert({
714+
db, user: actor.type.user, node, uid, message, ts,
715+
});
716+
717+
await cachePromise;
718+
719+
return node;
720+
}
721+
624722
/**
625723
* @param {Object} param
626724
* @param {File} param.file: The file to write.

src/backend/src/modules/puterfs/lib/PuterFSProvider.js

Lines changed: 3 additions & 97 deletions
Original file line numberDiff line numberDiff line change
@@ -204,104 +204,10 @@ class PuterFSProvider extends putility.AdvancedBase {
204204
* @returns {Promise<FSNodeContext>}
205205
*/
206206
async write_overwrite ({ context, node, file }) {
207-
const {
208-
tmp, fsentry_tmp, message, actor: inputActor,
209-
} = context.values;
210-
const actor = inputActor ?? Context.get('actor');
211-
212-
const sizeService = this.#services.get('sizeService');
213-
const resourceService = this.#services.get('resourceService');
214-
const svc_fsEntry = this.#services.get('fsEntryService');
215-
const svc_event = this.#services.get('event');
216-
217-
// TODO: fs:decouple-versions
218-
// add version hook externally so LLCWrite doesn't
219-
// need direct database access
220-
const db = this.#services.get('database').get(DB_WRITE, 'filesystem');
221-
222-
const svc_acl = this.#services.get('acl');
223-
if ( ! await svc_acl.check(actor, node, 'write') ) {
224-
throw await svc_acl.get_safe_acl_error(actor, node, 'write');
225-
}
226-
227-
const uid = await node.get('uid');
228-
229-
const bucket_region = node.entry.bucket_region;
230-
const bucket = node.entry.bucket;
231-
232-
const state_upload = await this.#storage_upload({
233-
uuid: node.entry.uuid,
234-
bucket,
235-
bucket_region,
236-
file,
237-
tmp: {
238-
...tmp,
239-
path: await node.get('path'),
240-
},
241-
});
242-
243-
if ( fsentry_tmp?.thumbnail_promise ) {
244-
fsentry_tmp.thumbnail = await fsentry_tmp.thumbnail_promise;
245-
delete fsentry_tmp.thumbnail_promise;
246-
}
247-
248-
const ts = Math.round(Date.now() / 1000);
249-
const raw_fsentry_delta = {
250-
modified: ts,
251-
accessed: ts,
252-
size: file.size,
253-
...fsentry_tmp,
254-
};
255-
256-
resourceService.register({
257-
uid,
258-
status: RESOURCE_STATUS_PENDING_CREATE,
259-
});
260-
261-
const filesize = file.size;
262-
sizeService.change_usage(actor.type.user.id, filesize);
263-
264-
// Meter ingress
265-
const ownerId = await node.get('user_id');
266-
const ownerActor = new Actor({
267-
type: new UserActorType({
268-
user: await get_user({ id: ownerId }),
269-
}),
270-
});
271-
this.#meteringService.incrementUsage(ownerActor, 'filesystem:ingress:bytes', filesize);
272-
273-
const entryOp = await svc_fsEntry.update(uid, raw_fsentry_delta);
274-
275-
// depends on fsentry, does not depend on S3
276-
const entryOpPromise = (async () => {
277-
await entryOp.awaitDone();
278-
resourceService.free(uid);
279-
})();
280-
281-
const cachePromise = (async () => {
282-
const svc_fileCache = this.#services.get('file-cache');
283-
await svc_fileCache.invalidate(node);
284-
})();
285-
286-
(async () => {
287-
await Promise.all([entryOpPromise, cachePromise]);
288-
svc_event.emit('fs.write.file', {
289-
node,
290-
context,
291-
});
292-
})();
293-
294-
// TODO (xiaochen): determine if this can be removed, post_insert handler need
295-
// to skip events from other servers (why? 1. current write logic is inside
296-
// the local server 2. broadcast system conduct "fire-and-forget" behavior)
297-
state_upload.post_insert({
298-
db, user: actor.type.user, node, uid, message, ts,
299-
});
300-
301-
await cachePromise;
302-
303-
return node;
207+
console.error('This .write_overwrite should not be called!');
208+
throw new Error('This .write_overwrite should not be called!');
304209
}
210+
305211
/**
306212
* @param {Object} param
307213
* @param {File} param.file: The file to write.

0 commit comments

Comments
 (0)