Skip to content

Commit 4de1444

Browse files
authored
Merge pull request #4 from onkernel/sayan/kernel-372-simplify-api-proxy-chain
Add scale to zero plugin
2 parents 9fbae97 + d650d7b commit 4de1444

File tree

11 files changed

+192
-6
lines changed

11 files changed

+192
-6
lines changed

KERNEL_README.md

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
# neko fork for onkernel
2+
3+
This is a public fork of the [m1k1o/neko](https://github.com/m1k1o/neko) repository.
4+
5+
## Overview
6+
7+
We maintain this fork to provide a customized `base` image that is used in our browser images at [onkernel/kernel-images](https://github.com/onkernel/kernel-images/tree/main/images).
8+
9+
## Building
10+
11+
To build images from this fork, use the build script from the repository root:
12+
13+
```bash
14+
# Build the base image
15+
./build base
16+
17+
# Build with custom repository and tag
18+
./build base --repository your-repo/neko --tag custom-tag
19+
```
20+
21+
The `--repository` and `--tag` options allow you to specify exactly which image you're building, making it easy to reference back to specific builds in `kernel-images`.
22+
23+
## Keeping in sync with upstream
24+
25+
To merge the latest changes from the upstream neko repository:
26+
27+
```bash
28+
# Run the sync script to create a new branch and merge upstream changes
29+
./scripts/sync-upstream.sh
30+
31+
# Or merge directly into your current branch
32+
./scripts/sync-upstream.sh --no-new-branch
33+
34+
# To merge a specific upstream branch
35+
./scripts/sync-upstream.sh --upstream-branch $branch
36+
```
37+
38+
After running the sync script:
39+
40+
1. Resolve any merge conflicts
41+
2. Test the build to ensure compatibility
42+
3. Push the changes and create a PR for review

server/Dockerfile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
ARG BASE_IMAGE=golang:1.24-bullseye
1+
ARG BASE_IMAGE=golang:1.25.0
22
FROM $BASE_IMAGE AS server
33

44
WORKDIR /src

server/Dockerfile.bookworm

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
ARG BASE_IMAGE=golang:1.24-bookworm
1+
ARG BASE_IMAGE=golang:1.25-bookworm
22
FROM $BASE_IMAGE AS server
33

44
WORKDIR /src

server/cmd/serve.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ package cmd
33
import (
44
"os"
55
"os/signal"
6+
"syscall"
67

78
"github.com/rs/zerolog"
89
"github.com/rs/zerolog/log"
@@ -236,7 +237,7 @@ func (c *serve) Run(cmd *cobra.Command, args []string) {
236237
c.logger.Info().Msg("neko ready")
237238

238239
quit := make(chan os.Signal, 1)
239-
signal.Notify(quit, os.Interrupt)
240+
signal.Notify(quit, os.Interrupt, syscall.SIGTERM)
240241
sig := <-quit
241242

242243
c.logger.Warn().Msgf("received %s, attempting graceful shutdown", sig)

server/go.mod

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,6 @@
11
module github.com/m1k1o/neko/server
22

3-
go 1.24.0
4-
5-
toolchain go1.24.5
3+
go 1.25.0
64

75
require (
86
github.com/PaesslerAG/gval v1.2.4
@@ -12,6 +10,7 @@ require (
1210
github.com/gorilla/websocket v1.5.3
1311
github.com/kataras/go-events v0.0.3
1412
github.com/mitchellh/mapstructure v1.5.0
13+
github.com/onkernel/kernel-images/server v0.0.0-20250912023508-e0ca1d95b771
1514
github.com/pion/ice/v2 v2.3.38
1615
github.com/pion/interceptor v0.1.40
1716
github.com/pion/logging v0.2.4

server/go.sum

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,8 @@ github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyua
5656
github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
5757
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA=
5858
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ=
59+
github.com/onkernel/kernel-images/server v0.0.0-20250912023508-e0ca1d95b771 h1:Z+Zu7ILww5/4q70h1oA+CYBCM0QCuNtAtGDUxjIyp1A=
60+
github.com/onkernel/kernel-images/server v0.0.0-20250912023508-e0ca1d95b771/go.mod h1:8BxVW6vmlK9as98BTOYIjsVPpXObs+b4aZyZ23JZf4Y=
5961
github.com/pelletier/go-toml/v2 v2.2.4 h1:mye9XuhQ6gvn5h28+VilKrrPoQVanw5PMw/TB0t5Ec4=
6062
github.com/pelletier/go-toml/v2 v2.2.4/go.mod h1:2gIqNv+qfxSVS7cM2xJQKtLSTLUE9V8t9Stt+h56mCY=
6163
github.com/pion/datachannel v1.5.10 h1:ly0Q26K1i6ZkGf42W7D4hQYR90pZwzFOjTq5AuCKk4o=

server/internal/plugins/manager.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ import (
1313
"github.com/m1k1o/neko/server/internal/config"
1414
"github.com/m1k1o/neko/server/internal/plugins/chat"
1515
"github.com/m1k1o/neko/server/internal/plugins/filetransfer"
16+
"github.com/m1k1o/neko/server/internal/plugins/scaletozero"
1617
"github.com/m1k1o/neko/server/pkg/types"
1718
)
1819

@@ -47,6 +48,7 @@ func New(config *config.Plugins) *ManagerCtx {
4748
// add built-in plugins
4849
manager.plugins.addPlugin(filetransfer.NewPlugin())
4950
manager.plugins.addPlugin(chat.NewPlugin())
51+
manager.plugins.addPlugin(scaletozero.NewPlugin())
5052

5153
return manager
5254
}
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
package scaletozero
2+
3+
import (
4+
"github.com/spf13/cobra"
5+
"github.com/spf13/viper"
6+
)
7+
8+
type Config struct {
9+
Enabled bool
10+
}
11+
12+
func (Config) Init(cmd *cobra.Command) error {
13+
cmd.PersistentFlags().Bool("scaletozero.enabled", false, "enable scale-to-zero")
14+
if err := viper.BindPFlag("scaletozero.enabled", cmd.PersistentFlags().Lookup("scaletozero.enabled")); err != nil {
15+
return err
16+
}
17+
18+
return nil
19+
}
20+
21+
func (c *Config) Set() {
22+
c.Enabled = viper.GetBool("scaletozero.enabled")
23+
}
Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
package scaletozero
2+
3+
import (
4+
"context"
5+
"sync"
6+
7+
"github.com/m1k1o/neko/server/pkg/types"
8+
"github.com/onkernel/kernel-images/server/lib/scaletozero"
9+
"github.com/rs/zerolog"
10+
"github.com/rs/zerolog/log"
11+
)
12+
13+
func NewManager(
14+
sessions types.SessionManager,
15+
config *Config,
16+
) *Manager {
17+
logger := log.With().Str("module", "scaletozero").Logger()
18+
19+
return &Manager{
20+
logger: logger,
21+
config: config,
22+
sessions: sessions,
23+
ctrl: scaletozero.NewUnikraftCloudController(),
24+
}
25+
}
26+
27+
type Manager struct {
28+
logger zerolog.Logger
29+
config *Config
30+
sessions types.SessionManager
31+
ctrl scaletozero.Controller
32+
mu sync.Mutex
33+
shutdown bool
34+
pending int
35+
}
36+
37+
func (m *Manager) Start() error {
38+
if !m.config.Enabled {
39+
return nil
40+
}
41+
m.logger.Info().Msg("scale-to-zero plugin enabled")
42+
43+
m.sessions.OnConnected(func(session types.Session) {
44+
m.mu.Lock()
45+
defer m.mu.Unlock()
46+
if m.shutdown {
47+
return
48+
}
49+
50+
m.pending++
51+
m.logger.Info().Msgf("connection started, disabling scale-to-zero (pending: %d)", m.pending)
52+
m.ctrl.Disable(context.Background())
53+
})
54+
55+
m.sessions.OnDisconnected(func(session types.Session) {
56+
m.mu.Lock()
57+
defer m.mu.Unlock()
58+
if m.shutdown {
59+
return
60+
}
61+
62+
m.pending--
63+
m.logger.Info().Msgf("connection started, disabling scale-to-zero (pending: %d)", m.pending)
64+
m.ctrl.Enable(context.Background())
65+
})
66+
67+
return nil
68+
}
69+
70+
func (m *Manager) Shutdown() error {
71+
m.mu.Lock()
72+
defer m.mu.Unlock()
73+
m.shutdown = true
74+
75+
m.logger.Info().Msgf("shutdown started, re-enabling scale-to-zero (pending: %d)", m.pending)
76+
for i := 0; i < m.pending; i++ {
77+
m.ctrl.Enable(context.Background())
78+
}
79+
80+
return nil
81+
}
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
package scaletozero
2+
3+
import (
4+
"github.com/m1k1o/neko/server/pkg/types"
5+
)
6+
7+
type Plugin struct {
8+
config *Config
9+
manager *Manager
10+
}
11+
12+
func NewPlugin() *Plugin {
13+
return &Plugin{
14+
config: &Config{},
15+
}
16+
}
17+
18+
func (p *Plugin) Name() string {
19+
return PluginName
20+
}
21+
22+
func (p *Plugin) Config() types.PluginConfig {
23+
return p.config
24+
}
25+
26+
func (p *Plugin) Start(m types.PluginManagers) error {
27+
p.manager = NewManager(m.SessionManager, p.config)
28+
return p.manager.Start()
29+
}
30+
31+
func (p *Plugin) Shutdown() error {
32+
return p.manager.Shutdown()
33+
}

0 commit comments

Comments
 (0)