KVSync - Syncing GORM Models with a Key-Value Store

Thuan Nguyen · June 10, 2024

I needed a way to achieve faster access to my data using a key-value store while keeping my GORM models synchronized. To address this, I created KVSync, a Go package designed to make the synchronization process straightforward and efficient.

What is KVSync?

KVSync allows you to synchronize your GORM models with a key-value store like Redis. One of the cool features is that you can define multiple keys for each model. For instance, you can have keys for fetching by ID, UUID, or even a composite key that combines both. This flexibility is really useful for different data retrieval needs.

Getting Started with KVSync

Installation

Installing KVSync is as simple as running go get github.com/ndthuan/kvsync.

Setting Up Sync

To get started, you need to define your models to implement the kvsync.Syncable interface. This involves providing sync keys that map your model fields. Once your models are set up, you configure your key-value store (like Redis) and create instances of RedisStore and KVSync.

type SyncedUser struct {
	gorm.Model
	UUID     string
	Username string
}

func (u SyncedUser) SyncKeys() map[string]string {
	return map[string]string{
		"id":        fmt.Sprintf("user:id:%d", u.ID),
		"uuid":      fmt.Sprintf("user:uuid:%s", u.UUID),
		"composite": fmt.Sprintf("user:composite:%d_%s", u.ID, u.UUID),
	}
}

Configuring the Key-Value Store

If you’re using Redis, you initialize your GORM DB instance, set up the Redis client, and register GORM callbacks to automate synchronization. This setup ensures that every time you create or update a model, it’s automatically synchronized with the key-value store.

Using KVSync

Once everything is set up, creating and updating your models is business as usual, and KVSync handles the synchronization. This means you don’t have to worry about manually keeping your key-value store in sync with your database changes.

Fetching Synced Models

KVSync makes it easy to fetch your models by any of the keys you’ve defined. Whether you need to retrieve data by ID, UUID, or a composite key, the process is straightforward and efficient.

By ID

user := SyncedUser{
    Model: gorm.Model{ID: 1},
}
kvSync.Fetch(&user, "id")

By UUID

user := SyncedUser{
    UUID: "test-uuid",
}
kvSync.Fetch(&user, "uuid")

By composite key

user := SyncedUser{
    Model: gorm.Model{ID: 1},
    UUID:  "test-uuid",
}
kvSync.Fetch(&user, "composite")

Final Thoughts

Creating KVSync has streamlined the way I manage synchronization between my GORM models and a key-value store. It’s flexible, efficient, and easy to set up, making it a great addition to any Go project that needs reliable data synchronization. If you’re looking for a solution to keep your models in sync with a key-value store, I highly recommend giving KVSync a try.