1
0
Fork 0
forked from jriou/coller

feat: Use snowflake identifiers

Fixes #29.

Signed-off-by: Julien Riou <julien@riou.xyz>
This commit is contained in:
Julien Riou 2025-09-20 08:37:16 +02:00
commit 2c3ca08dbf
Signed by: jriou
GPG key ID: 9A099EDA51316854
9 changed files with 24 additions and 39 deletions

View file

@ -10,7 +10,7 @@ type Config struct {
Title string `json:"title"`
DatabaseType string `json:"database_type"`
DatabaseDsn string `json:"database_dsn"`
IDLength int `json:"id_length"`
NodeID int64 `json:"node_id"`
PasswordLength int `json:"password_length"`
ExpirationInterval int `json:"expiration_interval"`
ListenAddress string `json:"listen_address"`
@ -36,7 +36,7 @@ func NewConfig() *Config {
Title: "Coller",
DatabaseType: "sqlite",
DatabaseDsn: "collerd.db",
IDLength: 5,
NodeID: 1,
PasswordLength: 16,
ExpirationInterval: 60, // 1 minute
ListenAddress: "0.0.0.0",
@ -88,8 +88,8 @@ func (c *Config) Check() error {
}
}
if c.IDLength <= 0 {
return fmt.Errorf("identifiers length must be greater than zero")
if c.NodeID < 0 || c.NodeID > 1023 {
return fmt.Errorf("node id must be between 0 and 1023")
}
if c.PasswordLength < internal.MIN_PASSWORD_LENGTH || c.PasswordLength > internal.MAX_PASSWORD_LENGTH {

View file

@ -7,11 +7,13 @@ import (
"strings"
"time"
"git.riou.xyz/jriou/coller/internal"
"github.com/bwmarrin/snowflake"
"gorm.io/driver/postgres"
"gorm.io/driver/sqlite"
"gorm.io/gorm"
"gorm.io/gorm/logger"
"git.riou.xyz/jriou/coller/internal"
)
type Database struct {
@ -22,6 +24,7 @@ type Database struct {
expiration int
languages []string
language string
node *snowflake.Node
}
var gconfig = &gorm.Config{
@ -48,6 +51,11 @@ func NewDatabase(logger *slog.Logger, config *Config) (d *Database, err error) {
logger.Debug("connected to the database")
node, err := snowflake.NewNode(config.NodeID)
if err != nil {
return nil, err
}
d = &Database{
logger: l,
db: db,
@ -56,6 +64,7 @@ func NewDatabase(logger *slog.Logger, config *Config) (d *Database, err error) {
expiration: config.Expiration,
languages: internal.ToLowerStringSlice(config.Languages),
language: strings.ToLower(config.Language),
node: node,
}
if err = d.UpdateSchema(); err != nil {
@ -132,6 +141,7 @@ func (d *Database) Create(content []byte, password string, encrypted bool, expir
}
note = &Note{
ID: d.node.Generate().String(),
Content: content,
ExpiresAt: time.Now().Add(time.Duration(expiration) * time.Second),
Encrypted: encrypted,

View file

@ -1,17 +1,11 @@
package server
import (
"fmt"
"time"
"git.riou.xyz/jriou/coller/internal"
"gorm.io/gorm"
)
const ID_MAX_RETRIES = 10
var idLength = 5
type Note struct {
ID string `json:"id" gorm:"primaryKey"`
Content []byte `json:"content" gorm:"not null"`
@ -21,27 +15,8 @@ type Note struct {
Language string `json:"language"`
}
// Generate ID and compress content before saving to the database
// Compress content before saving to the database
func (n *Note) BeforeCreate(trx *gorm.DB) (err error) {
for i := 0; i < ID_MAX_RETRIES; i++ {
if n.ID != "" {
continue
}
id := internal.GenerateChars(idLength)
var note Note
trx.Where("id = ?", id).Find(&note)
if note.ID == "" {
n.ID = id
continue
}
}
if n.ID == "" {
return fmt.Errorf("could not find unique id before creating the note")
}
n.Content = Compress(n.Content)
return nil
}

View file

@ -41,10 +41,6 @@ func NewServer(logger *slog.Logger, db *Database, config *Config, version string
}, nil
}
func (s *Server) SetIDLength(length int) {
idLength = length
}
func (s *Server) SetPasswordLength(length int) {
passwordLength = length
}