func()

in src/ulsp/controller/ulsp-daemon/ulsp_daemon.go [214:264]


func (c *controller) executePluginMethods(ctx context.Context, method string, handlerSync func(ctx context.Context, m *ulspplugin.Methods), handlerAsync func(ctx context.Context, m *ulspplugin.Methods)) error {
	if handlerSync == nil || handlerAsync == nil {
		return fmt.Errorf("handlers cannot be nil")
	}

	id, err := mapper.ContextToSessionUUID(ctx)
	if err != nil {
		return fmt.Errorf("getting session from context: %w", err)
	}

	if _, ok := c.pluginMethods[id]; !ok {
		return nil
	}

	methodLists, ok := c.pluginMethods[id][method]
	if !ok {
		// No need to execute if this method has no registered plugins.
		return nil
	}

	for _, current := range methodLists.Sync {
		handlerSync(ctx, current)
	}

	// Outer goroutine will spawn a goroutine for each asynchronous plugin method, then wait for them to complete with a timeout.
	// Plugins that implement asynchronous methods are responsible for respecting the context timeout or cancellation signal.
	c.wg.Add(1)
	go func() {
		defer c.wg.Done()

		// New context with its own timeout for asynchronous calls.
		asyncCtx := context.WithValue(context.Background(), entity.SessionContextKey, ctx.Value(entity.SessionContextKey))
		asyncCtx, cancel := context.WithTimeout(asyncCtx, _contextTimeoutSecondsAsync*time.Second)
		defer cancel()

		// Spawn a separate goroutine for each method's context, then wait for them all to complete.
		var innerWg sync.WaitGroup
		for _, current := range methodLists.Async {
			currentMethods := current
			innerWg.Add(1)
			go func() {
				defer innerWg.Done()
				handlerAsync(asyncCtx, currentMethods)
			}()
		}

		innerWg.Wait()
	}()

	return nil
}