Ctrl K
ComunidadGuías…

bldr/plugin/res-access-unixfs.go

Rama master · réplica de lectura del repositorio original.

Archivo original ↗Preguntar a KiBot
package bldr_plugin

import (
	"context"

	"github.com/aperturerobotics/controllerbus/directive"
	"github.com/aperturerobotics/starpc/rpcstream"
	"github.com/aperturerobotics/starpc/srpc"
	"github.com/pkg/errors"
	"github.com/s4wave/spacewave/db/unixfs"
	unixfs_access "github.com/s4wave/spacewave/db/unixfs/access"
	unixfs_rpc "github.com/s4wave/spacewave/db/unixfs/rpc"
	unixfs_rpc_client "github.com/s4wave/spacewave/db/unixfs/rpc/client"
)

// ParsePluginUnixfsID parses a unixfs ID and returns the plugin ID and matched prefix.
// Returns the plugin ID (which may be empty for current plugin) and the prefix.
// Returns empty matchedPrefix if no valid prefix is found.
//
// Matches UnixFS IDs like:
// - plugin-dist: matches the current plugin dist fs
// - plugin-assets: matches the current plugin assets fs
// - plugin-dist/{plugin-id}: matches the plugin dist fs for plugin-id
// - plugin-assets/{plugin-id}: matches the plugin assets fs for plugin-id
func ParsePluginUnixfsID(unixfsID string) (pluginID string, matchedPrefix string) {
	pluginID, matchedPrefix = srpc.CheckStripPrefix(unixfsID, []string{PluginDistFsIdPrefix, PluginAssetsFsIdPrefix})
	if matchedPrefix == "" {
		pluginID = ""
		if unixfsID == PluginDistFsId("") {
			matchedPrefix = PluginDistFsIdPrefix
		} else if unixfsID == PluginAssetsFsId("") {
			matchedPrefix = PluginAssetsFsIdPrefix
		}
	}
	return pluginID, matchedPrefix
}

// ValidatePluginUnixfsID validates a plugin unixfs ID and returns the plugin ID and matched prefix.
// If allowEmpty is true, allows empty plugin ID which refers to current plugin.
// Returns an error if the unixfsID is invalid.
func ValidatePluginUnixfsID(unixfsID string, allowEmpty bool) (pluginID string, matchedPrefix string, err error) {
	// An empty unixfs id is invalid.
	if unixfsID == "" {
		return "", "", errors.New("unixfs id must be set")
	}

	// The id must match a known prefix.
	pluginID, matchedPrefix = ParsePluginUnixfsID(unixfsID)
	if matchedPrefix == "" {
		return "", "", errors.New("unixfs id prefix must be plugin-dist or plugin-assets")
	}

	// A filesystem may select an immutable manifest instead of the current plugin.
	if _, _, err := ParsePluginArtifactID(pluginID, allowEmpty); err != nil {
		return "", "", err
	}

	return pluginID, matchedPrefix, nil
}

// ResolveAccessUnixfs resolves a AccessUnixfs directive with another plugin.
//
// Resolves unixfs IDs like:
//   - plugin-dist/{plugin-id}
//   - plugin-assets/{plugin-id}
//
// Returns nil, nil if the service ID does not match any of the known prefixes.
// Returns an error if the plugin id is invalid.
func ResolveAccessUnixfs(ctx context.Context, dir unixfs_access.AccessUnixFS, h LookupRpcClientHandler) (directive.Resolver, error) {
	// An empty unixfs id resolves nothing.
	unixfsID := dir.AccessUnixFSID()
	if unixfsID == "" {
		return nil, nil
	}

	// check if the unixfs ID matches one of the known prefixes.
	_, matchedPrefix := ParsePluginUnixfsID(unixfsID)
	if matchedPrefix == "" {
		// ignore
		return nil, nil
	}

	// AccessUnixFSFunc is a function to access a UnixFS.
	// Optionally pass a released function that may be called when the handle was released.
	// Returns a release function.
	// TODO: move this to a common place in unixfs_access or unixfs_rpc_client
	accessFunc := func(ctx context.Context, released func()) (*unixfs.FSHandle, func(), error) {
		// Wait for the plugin host client for this resolution.
		pluginHostClient, relFunc, err := h.WaitPluginHostClient(ctx, released)
		if err != nil {
			return nil, nil, err
		}

		// Open the filesystem handle through the plugin host RPC.
		pluginHostSvcClient := NewSRPCPluginHostClient(pluginHostClient)
		fsClient := rpcstream.NewRpcStreamClient(pluginHostSvcClient.PluginFsRpc, unixfsID, true)
		fsCursorSvcClient := unixfs_rpc.NewSRPCFSCursorServiceClient(fsClient)
		fsHandle, err := unixfs_rpc_client.BuildFSHandle(ctx, fsCursorSvcClient)
		if err != nil {
			if relFunc != nil {
				relFunc()
			}
			return nil, nil, err
		}

		// Release the handle and the host client together.
		return fsHandle, func() {
			fsHandle.Release()
			if relFunc != nil {
				relFunc()
			}
		}, nil
	}

	// Resolve the directive with the access function value.
	return directive.NewValueResolver([]unixfs_access.AccessUnixFSValue{accessFunc}), nil
}