Skip to content

Add memcached support #100

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions core/go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ go 1.22.1

require (
github.com/99designs/gqlgen v0.17.48
github.com/bradfitz/gomemcache v0.0.0-20230905024940-24af94b03874
github.com/elastic/go-elasticsearch/v8 v8.14.0
github.com/go-chi/chi/v5 v5.0.12
github.com/go-chi/cors v1.2.1
Expand Down
2 changes: 2 additions & 0 deletions core/go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ github.com/andybalholm/cascadia v1.3.2 h1:3Xi6Dw5lHF15JtdcmAHD3i1+T8plmv7BQ/nsVi
github.com/andybalholm/cascadia v1.3.2/go.mod h1:7gtRlve5FxPPgIgX36uWBX58OdBsSS6lUvCFb+h7KvU=
github.com/arbovm/levenshtein v0.0.0-20160628152529-48b4e1c0c4d0 h1:jfIu9sQUG6Ig+0+Ap1h4unLjW6YQJpKZVmUzxsD4E/Q=
github.com/arbovm/levenshtein v0.0.0-20160628152529-48b4e1c0c4d0/go.mod h1:t2tdKJDJF9BV14lnkjHmOQgcvEKgtqs5a1N3LNdJhGE=
github.com/bradfitz/gomemcache v0.0.0-20230905024940-24af94b03874 h1:N7oVaKyGp8bttX0bfZGmcGkjz7DLQXhAn3DNd3T0ous=
github.com/bradfitz/gomemcache v0.0.0-20230905024940-24af94b03874/go.mod h1:r5xuitiExdLAJ09PR7vBVENGvp4ZuTBeWTGtxuX3K+c=
github.com/cespare/xxhash/v2 v2.1.2 h1:YRXhKfTDauu4ajMg1TPgFO5jnlC2HCbmLXMcTG5cbYE=
github.com/cespare/xxhash/v2 v2.1.2/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
github.com/cpuguy83/go-md2man/v2 v2.0.4 h1:wfIWP927BUkWJb2NmU/kNDYIBTh/ziUX91+lVfRxZq4=
Expand Down
4 changes: 3 additions & 1 deletion core/graph/model/models_gen.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions core/graph/schema.graphqls
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ enum DatabaseType {
Redis,
ElasticSearch,
MariaDB,
Memcached,
}

type Column {
Expand Down
1 change: 1 addition & 0 deletions core/src/engine/engine.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ const (
DatabaseType_MongoDB = "MongoDB"
DatabaseType_Redis = "Redis"
DatabaseType_ElasticSearch = "ElasticSearch"
DatabaseType_Memcached = "Memcached"
)

type Engine struct {
Expand Down
15 changes: 15 additions & 0 deletions core/src/plugins/memcached/add.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package memcached

import (
"errors"

"github.com/clidey/whodb/core/src/engine"
)

func (p *MemcachedPlugin) AddStorageUnit(config *engine.PluginConfig, schema string, storageUnit string, fields map[string]string) (bool, error) {
return false, errors.ErrUnsupported
}

func (p *MemcachedPlugin) AddRow(config *engine.PluginConfig, schema string, storageUnit string, values []engine.Record) (bool, error) {
return false, errors.ErrUnsupported
}
22 changes: 22 additions & 0 deletions core/src/plugins/memcached/db.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
package memcached

import (
"fmt"

"github.com/bradfitz/gomemcache/memcache"
"github.com/clidey/whodb/core/src/common"
"github.com/clidey/whodb/core/src/engine"
)

func DB(config *engine.PluginConfig) (*memcache.Client, error) {
client := memcache.New(getAddress(config))
if client == nil {
return nil, fmt.Errorf("failed to create Memcached client")
}
return client, nil
}

func getAddress(config *engine.PluginConfig) string {
port := common.GetRecordValueOrDefault(config.Credentials.Advanced, "Port", "11211")
return fmt.Sprintf("%s:%s", config.Credentials.Hostname, port)
}
21 changes: 21 additions & 0 deletions core/src/plugins/memcached/delete.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
package memcached

import (
"github.com/bradfitz/gomemcache/memcache"
"github.com/clidey/whodb/core/src/engine"
)

func (p *MemcachedPlugin) DeleteRow(config *engine.PluginConfig, schema string, storageUnit string, values map[string]string) (bool, error) {
client, err := DB(config)
if err != nil {
return false, err
}
defer client.Close()

err = client.Delete(storageUnit)
if err != nil && err != memcache.ErrCacheMiss {
return false, err
}

return true, nil
}
151 changes: 151 additions & 0 deletions core/src/plugins/memcached/memcached.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,151 @@
package memcached

import (
"bufio"
"errors"
"fmt"
"net"
"strings"

"github.com/bradfitz/gomemcache/memcache"
"github.com/clidey/whodb/core/src/engine"
)

type MemcachedPlugin struct{}

func (p *MemcachedPlugin) IsAvailable(config *engine.PluginConfig) bool {
client, err := DB(config)
if err != nil {
return false
}
_, err = client.Get("test_key")
if err != nil && err != memcache.ErrCacheMiss {
return false
}
return true
}

func (p *MemcachedPlugin) GetDatabases(config *engine.PluginConfig) ([]string, error) {
return nil, errors.New("unsupported operation for Memcached")
}

func (p *MemcachedPlugin) GetSchema(config *engine.PluginConfig) ([]string, error) {
return nil, errors.New("unsupported operation for Memcached")
}

func (p *MemcachedPlugin) GetStorageUnits(config *engine.PluginConfig, schema string) ([]engine.StorageUnit, error) {
client, err := DB(config)
if err != nil {
return nil, err
}
defer client.Close()

rows, err := p.GetRows(config, schema, "", "", 0, 0)
if err != nil {
return nil, err
}

count := len(rows.Rows)

return []engine.StorageUnit{
{
Name: "default",
Attributes: []engine.Record{
{
Key: "Count",
Value: fmt.Sprintf("%v", count),
},
},
},
}, nil
}

func (p *MemcachedPlugin) GetRows(config *engine.PluginConfig, schema string, storageUnit string, where string, pageSize int, pageOffset int) (*engine.GetRowsResult, error) {
client, err := DB(config)
if err != nil {
return nil, err
}
defer client.Close()

conn, err := net.Dial("tcp", getAddress(config))
if err != nil {
return nil, fmt.Errorf("failed to connect to Memcached server: %v", err)
}
defer conn.Close()

scanner := bufio.NewScanner(conn)
slabs := make(map[int]int)

for scanner.Scan() {
line := scanner.Text()
if line == "END" {
break
}

if strings.HasPrefix(line, "STAT items") {
parts := strings.Split(line, ":")
if len(parts) > 2 {
slabID := 0
number := 0
fmt.Sscanf(parts[1], "%d", &slabID)
fmt.Sscanf(parts[2], "number %d", &number)
slabs[slabID] = number
}
}
}

rows := [][]string{}

for range slabs {
for scanner.Scan() {
line := scanner.Text()
if line == "END" {
break
}

parts := strings.Split(line, " ")
if len(parts) > 1 {
key := parts[1]

item, err := client.Get(key)
if err != nil {
return nil, fmt.Errorf("failed to retrieve value for key %s: %v", key, err)
}
rows = append(rows, []string{string(item.Value)})
}
}
}

if scanner.Err() != nil {
return nil, fmt.Errorf("error reading from connection: %v", scanner.Err())
}

return &engine.GetRowsResult{
Columns: []engine.Column{
{
Name: "Value",
Type: "string",
},
},
Rows: rows,
}, nil
}

func (p *MemcachedPlugin) GetGraph(config *engine.PluginConfig, schema string) ([]engine.GraphUnit, error) {
return nil, errors.New("unsupported operation for Memcached")
}

func (p *MemcachedPlugin) RawExecute(config *engine.PluginConfig, query string) (*engine.GetRowsResult, error) {
return nil, errors.New("unsupported operation for Memcached")
}

func (p *MemcachedPlugin) Chat(config *engine.PluginConfig, schema string, model string, previousConversation string, query string) ([]*engine.ChatMessage, error) {
return nil, errors.New("unsupported operation for Memcached")
}

func NewMemcachedPlugin() *engine.Plugin {
return &engine.Plugin{
Type: engine.DatabaseType_Memcached,
PluginFunctions: &MemcachedPlugin{},
}
}
32 changes: 32 additions & 0 deletions core/src/plugins/memcached/update.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
package memcached

import (
"errors"

"github.com/bradfitz/gomemcache/memcache"
"github.com/clidey/whodb/core/src/engine"
)

func (p *MemcachedPlugin) UpdateStorageUnit(config *engine.PluginConfig, schema string, storageUnit string, values map[string]string) (bool, error) {
client, err := DB(config)
if err != nil {
return false, err
}
defer client.Close()

if len(values) != 1 {
return false, errors.New("invalid number of fields for Memcached key")
}

value, ok := values["value"]
if !ok {
return false, errors.New("missing 'value' for update")
}

err = client.Set(&memcache.Item{Key: storageUnit, Value: []byte(value)})
if err != nil {
return false, err
}

return true, nil
}
2 changes: 2 additions & 0 deletions core/src/src.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import (
"github.com/clidey/whodb/core/src/engine"
"github.com/clidey/whodb/core/src/env"
"github.com/clidey/whodb/core/src/plugins/elasticsearch"
"github.com/clidey/whodb/core/src/plugins/memcached"
"github.com/clidey/whodb/core/src/plugins/mongodb"
"github.com/clidey/whodb/core/src/plugins/mysql"
"github.com/clidey/whodb/core/src/plugins/postgres"
Expand All @@ -24,6 +25,7 @@ func InitializeEngine() *engine.Engine {
MainEngine.RegistryPlugin(mongodb.NewMongoDBPlugin())
MainEngine.RegistryPlugin(redis.NewRedisPlugin())
MainEngine.RegistryPlugin(elasticsearch.NewElasticSearchPlugin())
MainEngine.RegistryPlugin(memcached.NewMemcachedPlugin())
return MainEngine
}

Expand Down
14 changes: 13 additions & 1 deletion dev/docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,17 @@ services:
- redis:/bitnami
networks:
- db
memcached:
image: bitnami/memcached
ports:
- '11211:11211'
environment:
MEMCACHED_CACHE_SIZE: 64
MEMCACHED_MAX_CONNECTIONS: 1024
volumes:
- memcached:/bitnami
networks:
- db
elasticsearch:
container_name: elasticsearch
image: docker.elastic.co/elasticsearch/elasticsearch:8.14.1
Expand Down Expand Up @@ -99,4 +110,5 @@ volumes:
mariadb:
mongo:
redis:
elasticsearch:
elasticsearch:
memcached:
1 change: 1 addition & 0 deletions frontend/src/components/icons.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -126,5 +126,6 @@ export const Icons = {
MongoDB: <svg className="w-6 h-6" xmlns="http://www.w3.org/2000/svg" width="64" height="64" viewBox="0 0 32 32"><path d="M15.9.087l.854 1.604c.192.296.4.558.645.802.715.715 1.394 1.464 2.004 2.266 1.447 1.9 2.423 4.01 3.12 6.292.418 1.394.645 2.824.662 4.27.07 4.323-1.412 8.035-4.4 11.12-.488.488-1.01.94-1.57 1.342-.296 0-.436-.227-.558-.436-.227-.383-.366-.82-.436-1.255-.105-.523-.174-1.046-.14-1.586v-.244C16.057 24.21 15.796.21 15.9.087z" fill="#599636"/><path d="M15.9.034c-.035-.07-.07-.017-.105.017.017.35-.105.662-.296.96-.21.296-.488.523-.767.767-1.55 1.342-2.77 2.963-3.747 4.776-1.3 2.44-1.97 5.055-2.16 7.808-.087.993.314 4.497.627 5.508.854 2.684 2.388 4.933 4.375 6.885.488.47 1.01.906 1.55 1.325.157 0 .174-.14.21-.244a4.78 4.78 0 0 0 .157-.68l.35-2.614L15.9.034z" fill="#6cac48"/><path d="M16.754 28.845c.035-.4.227-.732.436-1.063-.21-.087-.366-.26-.488-.453-.105-.174-.192-.383-.26-.575-.244-.732-.296-1.5-.366-2.248v-.453c-.087.07-.105.662-.105.75a17.37 17.37 0 0 1-.314 2.353c-.052.314-.087.627-.28.906 0 .035 0 .07.017.122.314.924.4 1.865.453 2.824v.35c0 .418-.017.33.33.47.14.052.296.07.436.174.105 0 .122-.087.122-.157l-.052-.575v-1.604c-.017-.28.035-.558.07-.82z" fill="#c2bfbf"/></svg>,
Redis: <svg className="w-6 h-6" viewBox="0 -18 256 256" xmlns="http://www.w3.org/2000/svg" preserveAspectRatio="xMinYMin meet"><path d="M245.97 168.943c-13.662 7.121-84.434 36.22-99.501 44.075-15.067 7.856-23.437 7.78-35.34 2.09-11.902-5.69-87.216-36.112-100.783-42.597C3.566 169.271 0 166.535 0 163.951v-25.876s98.05-21.345 113.879-27.024c15.828-5.679 21.32-5.884 34.79-.95 13.472 4.936 94.018 19.468 107.331 24.344l-.006 25.51c.002 2.558-3.07 5.364-10.024 8.988" fill="#912626"/><path d="M245.965 143.22c-13.661 7.118-84.431 36.218-99.498 44.072-15.066 7.857-23.436 7.78-35.338 2.09-11.903-5.686-87.214-36.113-100.78-42.594-13.566-6.485-13.85-10.948-.524-16.166 13.326-5.22 88.224-34.605 104.055-40.284 15.828-5.677 21.319-5.884 34.789-.948 13.471 4.934 83.819 32.935 97.13 37.81 13.316 4.881 13.827 8.9.166 16.02" fill="#C6302B"/><path d="M245.97 127.074c-13.662 7.122-84.434 36.22-99.501 44.078-15.067 7.853-23.437 7.777-35.34 2.087-11.903-5.687-87.216-36.112-100.783-42.597C3.566 127.402 0 124.67 0 122.085V96.206s98.05-21.344 113.879-27.023c15.828-5.679 21.32-5.885 34.79-.95C162.142 73.168 242.688 87.697 256 92.574l-.006 25.513c.002 2.557-3.07 5.363-10.024 8.987" fill="#912626"/><path d="M245.965 101.351c-13.661 7.12-84.431 36.218-99.498 44.075-15.066 7.854-23.436 7.777-35.338 2.087-11.903-5.686-87.214-36.112-100.78-42.594-13.566-6.483-13.85-10.947-.524-16.167C23.151 83.535 98.05 54.148 113.88 48.47c15.828-5.678 21.319-5.884 34.789-.949 13.471 4.934 83.819 32.933 97.13 37.81 13.316 4.88 13.827 8.9.166 16.02" fill="#C6302B"/><path d="M245.97 83.653c-13.662 7.12-84.434 36.22-99.501 44.078-15.067 7.854-23.437 7.777-35.34 2.087-11.903-5.687-87.216-36.113-100.783-42.595C3.566 83.98 0 81.247 0 78.665v-25.88s98.05-21.343 113.879-27.021c15.828-5.68 21.32-5.884 34.79-.95C162.142 29.749 242.688 44.278 256 49.155l-.006 25.512c.002 2.555-3.07 5.361-10.024 8.986" fill="#912626"/><path d="M245.965 57.93c-13.661 7.12-84.431 36.22-99.498 44.074-15.066 7.854-23.436 7.777-35.338 2.09C99.227 98.404 23.915 67.98 10.35 61.497-3.217 55.015-3.5 50.55 9.825 45.331 23.151 40.113 98.05 10.73 113.88 5.05c15.828-5.679 21.319-5.883 34.789-.948 13.471 4.935 83.819 32.934 97.13 37.811 13.316 4.876 13.827 8.897.166 16.017" fill="#C6302B"/><path d="M159.283 32.757l-22.01 2.285-4.927 11.856-7.958-13.23-25.415-2.284 18.964-6.839-5.69-10.498 17.755 6.944 16.738-5.48-4.524 10.855 17.067 6.391M131.032 90.275L89.955 73.238l58.86-9.035-17.783 26.072M74.082 39.347c17.375 0 31.46 5.46 31.46 12.194 0 6.736-14.085 12.195-31.46 12.195s-31.46-5.46-31.46-12.195c0-6.734 14.085-12.194 31.46-12.194" fill="#FFF"/><path d="M185.295 35.998l34.836 13.766-34.806 13.753-.03-27.52" fill="#621B1C"/><path d="M146.755 51.243l38.54-15.245.03 27.519-3.779 1.478-34.791-13.752" fill="#9A2928"/></svg>,
ElasticSearch: <svg className="w-6 h-6" preserveAspectRatio="xMidYMid" viewBox="0 0 256 286" xmlns="http://www.w3.org/2000/svg"><path d="m14.3443 80.1733h189.206c20.851 0 39.47-9.561 51.963-24.487-26.06-33.851-66.961-55.686-112.983-55.686-56.352 0-105.054 32.711-128.186 80.173" fill="#f0bf1a"/><path d="m187.5152 102.4438h-181.76c-3.722 12.721-5.755 26.163-5.755 40.086 0 13.924 2.033 27.367 5.755 40.087h181.76c21.825 0 40.087-17.816 40.087-40.087 0-22.27-17.816-40.086-40.087-40.086" fill="#07a5de"/><path d="m255.9996 228.7548c-12.414-14.591-30.883-23.868-51.559-23.868h-190.096c23.132 47.463 71.834 80.173 128.185 80.173 46.306 0 87.436-22.097 113.47-56.305" fill="#3ebeb0"/><path d="m5.7555 102.4438c-3.723 12.721-5.755 26.163-5.755 40.086 0 13.924 2.032 27.367 5.755 40.087h118.958c3.118-12.026 4.899-25.388 4.899-40.087 0-14.698-1.781-28.06-4.899-40.086z" fill="#231f20"/><path d="m70.8199 19.1528c-24.053 14.253-44.096 35.632-56.567 61.021h105.116c-10.69-24.498-27.615-44.986-48.549-61.021" fill="#d7a229"/><path d="m75.274 268.1347c20.488-16.48 36.968-38.305 47.213-63.248h-108.234c13.362 26.725 34.742 48.995 61.021 63.248" fill="#019b8f"/></svg>,
Memcached: <svg className="w-6 h-6" viewBox="0 0 254 254" xmlns="http://www.w3.org/2000/svg"><defs><linearGradient x1="50%" y1="100%" x2="50%" y2="0%" id="a"><stop stop-color="#574C4A" offset="0%"/><stop stop-color="#80716D" offset="100%"/></linearGradient><linearGradient x1="88.778%" y1="98.342%" x2="30.149%" y2="-8.68%" id="b"><stop stop-color="#268D83" offset="0%"/><stop stop-color="#2EA19E" offset="100%"/></linearGradient><radialGradient cx="41.406%" cy="42.708%" fx="41.406%" fy="42.708%" id="c"><stop stop-color="#DB7C7C" offset="0%"/><stop stop-color="#C83737" offset="100%"/></radialGradient><radialGradient cx="44.271%" cy="42.708%" fx="44.271%" fy="42.708%" id="d"><stop stop-color="#DB7C7C" offset="0%"/><stop stop-color="#C83737" offset="100%"/></radialGradient></defs><path d="M0 171.19V82.17C0 10.271 10.26 0 82.086 0h89.189C243.1 0 253.36 10.271 253.36 82.171v89.019c0 71.9-10.26 82.17-82.086 82.17H82.086C10.261 253.36 0 243.09 0 171.19z" fill="url(#a)"/><path d="M8.891.655C-3.562 79.583 2.953 153.48 2.953 153.48h38.928c-3.704-19.704-16.992-109.724-5.938-110.021 5.924.94 32.99 76.371 32.99 76.371s5.96-.742 11.958-.742 11.959.742 11.959.742 27.066-75.43 32.99-76.371c11.053.297-2.235 90.317-5.938 110.02h38.927s6.516-73.896-5.938-152.824H116.85C109.99.736 83.89 46.51 80.891 46.51 77.892 46.51 51.792.736 44.932.655H8.892z" fill="url(#b)" transform="translate(45.79 47.098)"/><path d="M73.214 144.267a9.213 9.213 0 1 1-18.427 0 9.213 9.213 0 0 1 18.427 0z" fill="url(#c)" transform="translate(45.79 47.098)"/><path d="M106.995 144.267a9.213 9.213 0 1 1-18.426 0 9.213 9.213 0 0 1 18.426 0z" fill="url(#d)" transform="translate(45.79 47.098)"/><path d="M196.846 50.362c5.618 38.026 6.936 74.52 6.833 101.705-.106 27.806-1.699 45.871-1.699 45.871h-32.767l-3.521 2.64h38.927s6.516-73.897-5.938-152.825l-1.835 2.61zm-103.154-.96c10.226 11.376 27.913 41.567 30.35 41.567-6.484-8.292-22.411-34.748-30.35-41.567zM79.094 87.918c-11.054.297 2.234 90.317 5.938 110.02H51.05l-2.307 2.64h38.928c-3.685-19.604-16.856-108.825-6.103-110.021-1.002-1.504-1.866-2.543-2.474-2.64zm89.896 0c-5.923.94-32.99 76.371-32.99 76.371s-5.96-.742-11.958-.742c-3.549 0-6.604.218-8.67.41l-.65 2.971s5.961-.742 11.96-.742c5.997 0 11.958.742 11.958.742s26.862-74.936 32.907-76.371c-.651-1.65-1.456-2.61-2.557-2.64z" opacity=".1"/><path d="M54.681 47.753c-12.453 78.928-5.938 152.825-5.938 152.825L51.035 198c-1.173-17.434-4.306-80.48 6.285-147.609h36.042c.763.01 1.787.635 2.969 1.65-2.36-2.626-4.322-4.274-5.609-4.29h-36.04zm107.959 0c-6.86.081-32.96 45.856-35.959 45.856 1.223 1.564 2.216 2.639 2.64 2.639 2.998 0 29.098-45.775 35.958-45.856h31.806l1.596-2.64H162.64zM84.207 93.196c8.755 13.148 30.515 73.732 30.515 73.732l.637-2.954c-5.372-14.732-25.844-69.961-30.987-70.778-.056.002-.11-.006-.165 0zm90.062 0c5.872 14.977-5.244 89.649-8.577 107.382l3.53-2.757c4.508-26.446 15.363-104.347 5.047-104.625z" opacity=".3" fill="#FFF"/></svg>,
},
}
1 change: 1 addition & 0 deletions frontend/src/generated/graphql.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ export type Column = {
export enum DatabaseType {
ElasticSearch = 'ElasticSearch',
MariaDb = 'MariaDB',
Memcached = 'Memcached',
MongoDb = 'MongoDB',
MySql = 'MySQL',
Postgres = 'Postgres',
Expand Down
Loading