service.go

 1package ollama
 2
 3import (
 4	"context"
 5	"fmt"
 6	"os/exec"
 7	"syscall"
 8	"time"
 9)
10
11var processManager = &ProcessManager{}
12
13// StartService starts the Ollama service if not already running
14func StartService(ctx context.Context) error {
15	if IsRunning(ctx) {
16		return nil // Already running
17	}
18
19	if !IsInstalled() {
20		return fmt.Errorf("Ollama is not installed")
21	}
22
23	processManager.mu.Lock()
24	defer processManager.mu.Unlock()
25
26	// Set up cleanup on first use
27	processManager.setupOnce.Do(func() {
28		setupCleanup()
29	})
30
31	// Start Ollama service
32	cmd := exec.CommandContext(ctx, "ollama", "serve")
33	cmd.SysProcAttr = &syscall.SysProcAttr{Setpgid: true}
34
35	if err := cmd.Start(); err != nil {
36		return fmt.Errorf("failed to start Ollama service: %w", err)
37	}
38
39	processManager.ollamaProcess = cmd
40	processManager.crushStartedOllama = true
41
42	// Wait for service to be ready
43	startTime := time.Now()
44	for time.Since(startTime) < ServiceStartTimeout {
45		if IsRunning(ctx) {
46			return nil
47		}
48		time.Sleep(100 * time.Millisecond)
49	}
50
51	return fmt.Errorf("Ollama service did not start within %v", ServiceStartTimeout)
52}
53
54// EnsureRunning ensures Ollama service is running, starting it if necessary
55func EnsureRunning(ctx context.Context) error {
56	// Always ensure cleanup is set up, even if Ollama was already running
57	processManager.setupOnce.Do(func() {
58		setupCleanup()
59	})
60	return StartService(ctx)
61}
62
63// EnsureModelLoaded ensures a model is loaded, loading it if necessary
64func EnsureModelLoaded(ctx context.Context, modelName string) error {
65	if err := EnsureRunning(ctx); err != nil {
66		return err
67	}
68
69	running, err := IsModelRunning(ctx, modelName)
70	if err != nil {
71		return fmt.Errorf("failed to check if model is running: %w", err)
72	}
73
74	if running {
75		return nil // Already loaded
76	}
77
78	// Load the model
79	loadCtx, cancel := context.WithTimeout(ctx, ModelLoadTimeout)
80	defer cancel()
81
82	if err := LoadModel(loadCtx, modelName); err != nil {
83		return fmt.Errorf("failed to load model %s: %w", modelName, err)
84	}
85
86	return nil
87}