Address code review: add constants and improve documentation

Co-authored-by: RPRX <63339210+RPRX@users.noreply.github.com>
This commit is contained in:
copilot-swe-agent[bot]
2026-02-04 22:14:53 +00:00
parent ee6f422148
commit 1ca08845e3
2 changed files with 33 additions and 14 deletions

View File

@@ -453,6 +453,11 @@ func (c *SplitHTTPConfig) Build() (proto.Message, error) {
return config, nil return config, nil
} }
// XDriveConfig represents the configuration for the XDRIVE transport.
// For the "local" service, secrets[0] should be "client" for client-side
// or "server" for server-side.
// For "Google Drive" service, secrets should contain [role, ClientID, ClientSecret, RefreshToken]
// where role is "client" or "server".
type XDriveConfig struct { type XDriveConfig struct {
RemoteFolder string `json:"remoteFolder"` RemoteFolder string `json:"remoteFolder"`
Service string `json:"service"` Service string `json:"service"`
@@ -463,9 +468,14 @@ type XDriveConfig struct {
func (c *XDriveConfig) Build() (proto.Message, error) { func (c *XDriveConfig) Build() (proto.Message, error) {
switch c.Service { switch c.Service {
case "local": case "local":
// For local service, secrets[0] must be "client" or "server"
if len(c.Secrets) < 1 {
return nil, errors.New("local service needs secrets[0] set to 'client' or 'server'")
}
case "Google Drive": case "Google Drive":
if len(c.Secrets) != 3 { // For Google Drive, secrets should be [role, ClientID, ClientSecret, RefreshToken]
return nil, errors.New("Google Drive needs 3 secrets in order of ClientID, ClientSecret, RefreshToken") if len(c.Secrets) != 4 {
return nil, errors.New("Google Drive needs 4 secrets: role ('client' or 'server'), ClientID, ClientSecret, RefreshToken")
} }
default: default:
return nil, errors.New("unsupported service") return nil, errors.New("unsupported service")

View File

@@ -23,6 +23,20 @@ import (
const protocolName = "xdrive" const protocolName = "xdrive"
// Configuration constants
const (
// ReadPollInterval is the interval for polling when reading data
ReadPollInterval = 100 * time.Millisecond
// ServerPollInterval is the interval for polling new connections on server
ServerPollInterval = 500 * time.Millisecond
// ReadTimeout is the timeout for read operations
ReadTimeout = 10 * time.Second
// RetentionWindow is how long files are kept before cleanup
RetentionWindow = 10 * time.Second
// CleanupInterval is how often the cleanup routine runs
CleanupInterval = 5 * time.Second
)
// DriveService defines the interface for remote storage services // DriveService defines the interface for remote storage services
type DriveService interface { type DriveService interface {
// Login authenticates with the service (no-op for local) // Login authenticates with the service (no-op for local)
@@ -224,9 +238,7 @@ func (c *XdriveConnection) Read(b []byte) (int, error) {
prefix := fmt.Sprintf("%s-%s-", c.sessionID, readDirection) prefix := fmt.Sprintf("%s-%s-", c.sessionID, readDirection)
// Poll for the expected file with timeout // Poll for the expected file with timeout
pollInterval := 100 * time.Millisecond deadline := time.Now().Add(ReadTimeout)
timeout := 10 * time.Second
deadline := time.Now().Add(timeout)
for time.Now().Before(deadline) { for time.Now().Before(deadline) {
select { select {
@@ -238,7 +250,7 @@ func (c *XdriveConnection) Read(b []byte) (int, error) {
} }
// List files within retention window // List files within retention window
files, err := c.service.List(c.ctx, prefix, 10*time.Second) files, err := c.service.List(c.ctx, prefix, RetentionWindow)
if err != nil { if err != nil {
return 0, err return 0, err
} }
@@ -281,7 +293,7 @@ func (c *XdriveConnection) Read(b []byte) (int, error) {
} }
} }
time.Sleep(pollInterval) time.Sleep(ReadPollInterval)
} }
return 0, errors.New("read timeout") return 0, errors.New("read timeout")
@@ -471,8 +483,7 @@ func Serve(ctx context.Context, address net.Address, port net.Port, streamSettin
// pollForConnections polls the folder for new upload files indicating new connections // pollForConnections polls the folder for new upload files indicating new connections
func (s *Server) pollForConnections() { func (s *Server) pollForConnections() {
pollInterval := 500 * time.Millisecond ticker := time.NewTicker(ServerPollInterval)
ticker := time.NewTicker(pollInterval)
defer ticker.Stop() defer ticker.Stop()
for { for {
@@ -490,7 +501,7 @@ func (s *Server) pollForConnections() {
// checkForNewConnections checks for files from new client sessions // checkForNewConnections checks for files from new client sessions
func (s *Server) checkForNewConnections() { func (s *Server) checkForNewConnections() {
// List all files within the retention window // List all files within the retention window
files, err := s.service.List(s.ctx, "", 10*time.Second) files, err := s.service.List(s.ctx, "", RetentionWindow)
if err != nil { if err != nil {
errors.LogWarning(s.ctx, "failed to list files: ", err) errors.LogWarning(s.ctx, "failed to list files: ", err)
return return
@@ -533,9 +544,7 @@ func (s *Server) checkForNewConnections() {
// cleanupOldFiles removes files older than the retention window // cleanupOldFiles removes files older than the retention window
func (s *Server) cleanupOldFiles() { func (s *Server) cleanupOldFiles() {
cleanupInterval := 5 * time.Second ticker := time.NewTicker(CleanupInterval)
retentionWindow := 10 * time.Second
ticker := time.NewTicker(cleanupInterval)
defer ticker.Stop() defer ticker.Stop()
for { for {
@@ -545,7 +554,7 @@ func (s *Server) cleanupOldFiles() {
case <-s.closeDone.Wait(): case <-s.closeDone.Wait():
return return
case <-ticker.C: case <-ticker.C:
s.doCleanup(retentionWindow) s.doCleanup(RetentionWindow)
} }
} }
} }