Sync implementation using cr-sqlite + websockets, across JS and CLI clients #1

Merged
aynish merged 4 commits from testing-sync into main 2024-08-31 18:06:10 -07:00
3 changed files with 190 additions and 207 deletions
Showing only changes of commit a593d23f23 - Show all commits

View file

@ -14,9 +14,6 @@
const sqlite = await initWasm(() => wasmUrl); const sqlite = await initWasm(() => wasmUrl);
db = await sqlite.open('todo.db'); db = await sqlite.open('todo.db');
await db.exec(`
DROP TABLE todos;
`);
await db.exec(` await db.exec(`
CREATE TABLE IF NOT EXISTS todos ( CREATE TABLE IF NOT EXISTS todos (
id BLOB PRIMARY KEY NOT NULL, id BLOB PRIMARY KEY NOT NULL,
@ -54,9 +51,9 @@
function sendChangesToServer(changes) { function sendChangesToServer(changes) {
const formattedChanges = changes.map(change => ({ const formattedChanges = changes.map(change => ({
TableName: change[0], TableName: change[0],
PK: Array.isArray(change[1]) ? btoa(change[1]) : btoa(change[1]), PK: Array.isArray(change[1]) ? btoa(String.fromCharCode.apply(null, change[1])) : btoa(change[1]),
ColumnName: change[2], ColumnName: change[2],
Value: Array.isArray(change[3]) ? btoa(String.fromCharCode.apply(null, change[3])) : btoa(change[3]), Value: Array.isArray(change[3]) ? btoa(String.fromCharCode.apply(null, change[3])) : change[3],
ColVersion: Number(change[4]), ColVersion: Number(change[4]),
DBVersion: Number(change[5]), DBVersion: Number(change[5]),
SiteID: Array.isArray(change[6]) ? btoa(new TextDecoder('utf8').decode(change[6])) : btoa(change[6]), SiteID: Array.isArray(change[6]) ? btoa(new TextDecoder('utf8').decode(change[6])) : btoa(change[6]),

View file

@ -76,7 +76,6 @@ type CRSQLChange struct {
Seq int64 Seq int64
} }
func (m *model) addTodo(todo string) { func (m *model) addTodo(todo string) {
id, err := uuid.NewV7() id, err := uuid.NewV7()
if err != nil { if err != nil {
@ -114,7 +113,6 @@ func (m *model) addTodo(todo string) {
change.Value = base64.StdEncoding.EncodeToString(valueRaw) change.Value = base64.StdEncoding.EncodeToString(valueRaw)
change.SiteID = base64.StdEncoding.EncodeToString(siteIDRaw) change.SiteID = base64.StdEncoding.EncodeToString(siteIDRaw)
changes = append(changes, change) changes = append(changes, change)
fmt.Println(change) fmt.Println(change)
} }
@ -142,7 +140,6 @@ func (m *model) sendToWebSocket(changes []CRSQLChange) {
} }
} }
func (m *model) loadTodos() { func (m *model) loadTodos() {
rows, err := m.db.Query("SELECT content FROM todos") rows, err := m.db.Query("SELECT content FROM todos")
if err != nil { if err != nil {

View file

@ -78,7 +78,7 @@ type CRSQLChange struct {
TableName string TableName string
PK []byte PK []byte
ColumnName string ColumnName string
Value []byte Value any
ColVersion int64 ColVersion int64
DBVersion int64 DBVersion int64
SiteID []byte SiteID []byte
@ -97,15 +97,12 @@ func mapToCRSQLChange(m map[string]interface{}) (CRSQLChange, error) {
change.CL = int64(m["CL"].(float64)) change.CL = int64(m["CL"].(float64))
change.Seq = int64(m["Seq"].(float64)) change.Seq = int64(m["Seq"].(float64))
// Still unsure about this, it can encode anything
if m["Value"] != nil {
change.Value = m["Value"]
}
// Handle []byte fields // Handle []byte fields
change.PK, err = decodeBase64ToByteArray(m["PK"].(string)) change.PK, err = decodeBase64ToByteArray(m["PK"].(string))
if err != nil {
return change, err
}
//fmt.Println(m["PK"])
//fmt.Println(m["PK"].(string))
//fmt.Println(base64.URLEncoding.DecodeString(m["PK"].(string)))
change.Value, err = decodeBase64ToByteArray(m["Value"].(string))
if err != nil { if err != nil {
return change, err return change, err
} }
@ -118,7 +115,6 @@ func mapToCRSQLChange(m map[string]interface{}) (CRSQLChange, error) {
return change, nil return change, nil
} }
func decodeBase64ToByteArray(encodedString string) ([]uint8, error) { func decodeBase64ToByteArray(encodedString string) ([]uint8, error) {
// Decode the base64 string // Decode the base64 string
decodedBytes, err := base64.StdEncoding.DecodeString(encodedString) decodedBytes, err := base64.StdEncoding.DecodeString(encodedString)
@ -145,7 +141,6 @@ func decodeBase64ToByteArray(encodedString string) ([]uint8, error) {
return intSlice, nil return intSlice, nil
} }
func applyChanges(changes []interface{}) { func applyChanges(changes []interface{}) {
tx, _ := db.Begin() tx, _ := db.Begin()
for i, change := range changes { for i, change := range changes {
@ -174,7 +169,6 @@ func applyChanges(changes []interface{}) {
tx.Commit() tx.Commit()
} }
func broadcastChanges(sender *websocket.Conn, changes interface{}) { func broadcastChanges(sender *websocket.Conn, changes interface{}) {
for client := range clients { for client := range clients {
if client != sender { if client != sender {
@ -184,13 +178,9 @@ func broadcastChanges(sender *websocket.Conn, changes interface{}) {
} }
func main() { func main() {
var err error var err error
val, err := base64.StdEncoding.DecodeString("MTY3LDU0LDQ5LDY3LDExMyw2MCw3NiwxMjAsMTU2LDExMCwyMjcsMTc2LDE4NCwyMjksMjQxLDE0Mw==")
decoded, _ := base64.StdEncoding.DecodeString("MTY3LDU0LDQ5LDY3LDExMyw2MCw3NiwxMjAsMTU2LDExMCwyMjcsMTc2LDE4NCwyMjksMjQxLDE0Mw==")
if err != nil { if err != nil {
log.Fatal("error:", err) log.Fatal("error:", err)
} }
fmt.Printf("%q\n", val)
fmt.Printf("%q\n", decoded)
sql.Register("sqlite3_with_extensions", sql.Register("sqlite3_with_extensions",
&sqlite3.SQLiteDriver{ &sqlite3.SQLiteDriver{
Extensions: []string{ Extensions: []string{
@ -208,4 +198,3 @@ func main() {
http.HandleFunc("/sync", handleWebSocket) http.HandleFunc("/sync", handleWebSocket)
log.Fatal(http.ListenAndServe(":8080", nil)) log.Fatal(http.ListenAndServe(":8080", nil))
} }