Skip to content

Conversation

@XiaochenCui
Copy link
Contributor

@XiaochenCui XiaochenCui commented Oct 6, 2025

This is the first release of client-replica, check the RFC for details: https://github.com/XiaochenCui/puter/blob/fs/client-replica/doc/RFCS/20250821_client_replica_file_system.md

It's safe to merge and deploy it without update the config, no client will use client-replica in this case.

How to review

  • The implementation of fs-tree-manager process: src/fs_tree_manager
    • entry: src/fs_tree_manager/server.go
    • protobuf generated code: src/fs_tree_manager/go and src/fs_tree_manager/js
    • merkle tree: src/fs_tree_manager/merkle
    • core data structure and rpc: src/fs_tree_manager/proto/fs_tree_manager.proto
  • Client (puter-js): src/puter-js/src/modules/FileSystem/replica
  • puter backend (act as a proxy): src/backend/src/routers/filesystem_api/fs_tree_manager

Other code are hooks for integration with the existing codebase.

Config

  • init config file: cp src/fs_tree_manager/example-config.yaml src/fs_tree_manager/config.yaml
  • update config src/fs_tree_manager/config.yaml, set mysql args to the same as puter backend
  • update puter backend config, set the endpoint of fs_tree_manager:
{
  ...
  "services": {
    ...
    "client-replica": {
      "enabled": true,
      "fs_tree_manager_url": "<ip>:<port>"
    }
  }
}

Deploy

# build
docker build -t fs_tree_manager -f src/fs_tree_manager/Dockerfile src/fs_tree_manager

# run
docker compose -f src/fs_tree_manager/docker-compose.yml up

Whitelist

Whitelist is done by permission service:

        const svc_permission = Context.get('services').get('permission');
        const can_access = await svc_permission.check('endpoint:replica/fetch');
        if ( ! can_access ) {
            return socket.emit('replica/fetch/error', {
                success: false,
                error: { message: 'permission denied' },
            });
        }

@XiaochenCui XiaochenCui force-pushed the fs/client-replica branch 4 times, most recently from dd647d5 to 97c78fc Compare October 10, 2025 19:08
@XiaochenCui XiaochenCui marked this pull request as ready for review October 10, 2025 19:13
@XiaochenCui
Copy link
Contributor Author

@KernelDeimos @jelveh this PR is ready for review/merge

Copy link
Contributor

@KernelDeimos KernelDeimos left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Biggest concerns are:

  • filesystem events should be used instead of adding hooks everywhere
  • database UPDATE added to move operation; I don't understand what it's fixing

Go code looks good to me, but I reviewed it very quickly since it's more outside the concern of the core backend.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(1) Why is this file changed? There do not appear to be any functional changes here - I think these changes were included by accident.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

See previous comment "(1)"


const db = services.get('database').get(DB_WRITE, 'filesystem');
await db.write(
'UPDATE fsentries SET parent_uid = ? WHERE uuid = ?',
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's a bit concerning to see this change. If the parent_uid was not already being updated, that would mean move is currently broken. However, I just tried moving a file in prod - move is not broken.

A second area of concern is I was informed that the relica code won't do anything if it's not enabled, however this looks like a database operation that's happening every time a file is moved without any feature flag being checked.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it's not broken but the parent_uid is wrong without this patch, see here for details:

https://github.com/XiaochenCui/puter/blob/fs/client-replica/doc/RFCS/20250821_client_replica_file_system.md#fsentry-parent

the code below this patch doesn't set the parent_uid correctly:

const op_update = await svc_fsEntry.update(node.uid, {
...(
await node.get('parent_uid') !== await new_parent.get('uid')
? { parent_uid: await new_parent.get('uid') }
: {}
),
path: new_path,
name: new_name,
...(metadata ? { metadata } : {}),
});

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I found parent_uid is correct after moving, I'll look into this later

console.error('user_id is missing');
return;
}
await sendFSNew(user_id, response);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It isn't necessary to add these hooks into the filesystem implementation provider. This puts the responsibility on file system providers to inform the client-replica system of what's happening, requiring duplication of effort any time a new provider is added. This sort of thing is why we have filesystem events like fs.create.*, for example here. If the events don't have enough information or some events are missing (it looks like we don't have an event for delete yet) then the events should be updated to support that.

}
if ( config.env === 'dev' && process.env.DEBUG ) {
console.log(`request url: ${req.url}, body: ${JSON.stringify(req.body)}`);
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why is this conditional debug log being removed? This only prints of the DEBUG environment variable is set - it allows easier debugging of endpoints when Puter is initiated with a terminal input like: DEBUG=1 npm start

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

oh, this log was added by me. I don't know others are using it - will revert this

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Honestly I thought I added it, but let's keep it - it seems useful

})();

// ================== client-replica hook start ==================
// "rename" hook
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If we can use events instead of this hook here that would be better.

@XiaochenCui XiaochenCui force-pushed the fs/client-replica branch 7 times, most recently from ac6de4a to 9f4d6d0 Compare October 21, 2025 00:08
stash changes

stash changes

stash changes

stash changes

stash changes

stash changes

stash changes
stash changes

stash changes

stash changes

stash changes

stash changes

stash changes

stash changes

stash changes

stash changes
stash changes

stash changes

stash changes

stash changes

stash changes

stash changes

stash changes

stash changes

stash changes

stash changes
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants