Skip to content

Commit 6c8a1e5

Browse files
committed
fix(scaling): yarn install queuing + refactor
1 parent a6ec3d4 commit 6c8a1e5

File tree

7 files changed

+536
-384
lines changed

7 files changed

+536
-384
lines changed

cmd/server/main.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,7 @@ func main() {
8888
node.WithHealthCheckWait(cfg.HealthCheckWait),
8989
node.WithHealthCheckInterval(cfg.HealthCheckInterval),
9090
node.WithRequestTimeout(cfg.NodeRequestTimeout),
91+
node.WithYarnQueue(cfg.MaxConcurrentYarnInstalls),
9192
)
9293
if err != nil {
9394
err = pkgerrors.WrapWithCode(err, pkgerrors.ErrorCodeInternalError, "failed to create process manager")

pkg/config/config.go

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,9 @@ type Config struct {
3131
HealthCheckWait time.Duration `envconfig:"HEALTH_CHECK_WAIT" default:"30s" description:"Timeout for health check"`
3232
HealthCheckInterval time.Duration `envconfig:"HEALTH_CHECK_INTERVAL" default:"500ms" description:"Interval for health check polling"`
3333
NodeRequestTimeout time.Duration `envconfig:"NODE_REQUEST_TIMEOUT" default:"30s" description:"Timeout for Node.js requests"`
34+
35+
// Yarn configuration
36+
MaxConcurrentYarnInstalls int `envconfig:"MAX_CONCURRENT_YARN_INSTALLS" default:"3" description:"Maximum concurrent yarn install operations"`
3437
}
3538

3639
// LoadConfig loads configuration from environment variables and returns a Config
@@ -96,5 +99,8 @@ func (c *Config) Validate() error {
9699
if c.NodeRequestTimeout <= 0 {
97100
return fmt.Errorf("node request timeout must be positive")
98101
}
102+
if c.MaxConcurrentYarnInstalls <= 0 {
103+
return fmt.Errorf("max concurrent yarn installs must be positive")
104+
}
99105
return nil
100106
}

pkg/node/dependency.go

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
package node
2+
3+
import (
4+
"strings"
5+
6+
"github.com/socialgouv/xfuncjs-server/pkg/logger"
7+
)
8+
9+
// DependencyResolver handles dependency resolution operations
10+
type DependencyResolver struct {
11+
logger logger.Logger
12+
}
13+
14+
// NewDependencyResolver creates a new dependency resolver
15+
func NewDependencyResolver(logger logger.Logger) *DependencyResolver {
16+
return &DependencyResolver{
17+
logger: logger.WithField("component", "dependency-resolver"),
18+
}
19+
}
20+
21+
// ResolveDependencies processes and resolves dependencies from the input specification
22+
func (dr *DependencyResolver) ResolveDependencies(inputDependencies map[string]string, workspaceMap map[string]string, workspaceRoot string, logger logger.Logger) (map[string]interface{}, error) {
23+
dependencies := make(map[string]interface{})
24+
25+
logger.WithField("input_dependencies", inputDependencies).
26+
Info("Starting dependency processing")
27+
28+
// Add user-specified dependencies
29+
for k, v := range inputDependencies {
30+
resolvedDep := v
31+
32+
if strings.HasPrefix(v, "link:") {
33+
// Resolve workspace package dependencies
34+
if resolved, _, resolveErr := ResolveWorkspacePackage(v, workspaceRoot, workspaceMap, logger); resolveErr != nil {
35+
logger.WithField("dependency", k).
36+
WithField("value", v).
37+
WithField("error", resolveErr.Error()).
38+
Warn("Failed to resolve workspace dependency, using original value")
39+
} else {
40+
resolvedDep = resolved
41+
}
42+
}
43+
44+
dependencies[k] = resolvedDep
45+
}
46+
47+
logger.WithField("total_dependencies", len(dependencies)).
48+
Info("Completed dependency processing")
49+
50+
return dependencies, nil
51+
}
52+
53+
// ValidateDependencies validates that all dependencies are properly formatted
54+
func (dr *DependencyResolver) ValidateDependencies(dependencies map[string]interface{}) error {
55+
// Add validation logic here if needed
56+
// For now, we'll just return nil as the current implementation doesn't require validation
57+
return nil
58+
}

pkg/node/options.go

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,18 @@ func WithRequestTimeout(timeout time.Duration) ProcessManagerOption {
3636
}
3737
}
3838

39+
// WithYarnQueue sets the yarn installer with queue support
40+
func WithYarnQueue(maxConcurrentYarnInstalls int) ProcessManagerOption {
41+
return func(pm *ProcessManager) {
42+
// Initialize the global yarn queue if not already initialized
43+
if GetYarnQueue() == nil {
44+
InitializeYarnQueue(maxConcurrentYarnInstalls, pm.logger)
45+
}
46+
pm.yarnInstaller = NewYarnInstaller(GetYarnQueue(), pm.logger)
47+
pm.dependencyResolver = NewDependencyResolver(pm.logger)
48+
}
49+
}
50+
3951
// SetNodeServerPort sets the base port for the Node.js HTTP servers
4052
func (pm *ProcessManager) SetNodeServerPort(port int) {
4153
pm.nodeServerPort = port

0 commit comments

Comments
 (0)