Browse Source

schema change for #1345

Convert the flat list of channels for always-on clients
to a map from channel names to channel-user modes.
tags/v2.5.0-rc1
Shivaram Lingamneni 3 years ago
parent
commit
c0bc485840
2 changed files with 67 additions and 2 deletions
  1. 66
    1
      irc/database.go
  2. 1
    1
      irc/import.go

+ 66
- 1
irc/database.go View File

@@ -24,7 +24,7 @@ const (
24 24
 	// 'version' of the database schema
25 25
 	keySchemaVersion = "db.version"
26 26
 	// latest schema of the db
27
-	latestDbSchema = 18
27
+	latestDbSchema = 19
28 28
 
29 29
 	keyCloakSecret = "crypto.cloak_secret"
30 30
 )
@@ -903,6 +903,66 @@ func schemaChangeV17ToV18(config *Config, tx *buntdb.Tx) error {
903 903
 	return nil
904 904
 }
905 905
 
906
+// #1345: persist the channel-user modes of always-on clients
907
+func schemaChangeV18To19(config *Config, tx *buntdb.Tx) error {
908
+	channelToAmodesCache := make(map[string]map[string]modes.Mode)
909
+	joinedto := "account.joinedto "
910
+	var accounts []string
911
+	var channels [][]string
912
+	tx.AscendGreaterOrEqual("", joinedto, func(key, value string) bool {
913
+		if !strings.HasPrefix(key, joinedto) {
914
+			return false
915
+		}
916
+		accounts = append(accounts, strings.TrimPrefix(key, joinedto))
917
+		var ch []string
918
+		if value != "" {
919
+			ch = strings.Split(value, ",")
920
+		}
921
+		channels = append(channels, ch)
922
+		return true
923
+	})
924
+
925
+	for i := 0; i < len(accounts); i++ {
926
+		account := accounts[i]
927
+		channels := channels[i]
928
+		tx.Delete(joinedto + account)
929
+		newValue := make(map[string]string, len(channels))
930
+		for _, channel := range channels {
931
+			chcfname, err := CasefoldChannel(channel)
932
+			if err != nil {
933
+				continue
934
+			}
935
+			// get amodes from the channelToAmodesCache, fill if necessary
936
+			amodes, ok := channelToAmodesCache[chcfname]
937
+			if !ok {
938
+				amodeStr, _ := tx.Get("channel.accounttoumode " + chcfname)
939
+				if amodeStr != "" {
940
+					jErr := json.Unmarshal([]byte(amodeStr), &amodes)
941
+					if jErr != nil {
942
+						log.Printf("error retrieving amodes for %s: %v\n", channel, jErr)
943
+						amodes = nil
944
+					}
945
+				}
946
+				// setting/using the nil value here is ok
947
+				channelToAmodesCache[chcfname] = amodes
948
+			}
949
+			if mode, ok := amodes[account]; ok {
950
+				newValue[channel] = string(mode)
951
+			} else {
952
+				newValue[channel] = ""
953
+			}
954
+		}
955
+		newValueBytes, jErr := json.Marshal(newValue)
956
+		if jErr != nil {
957
+			log.Printf("couldn't serialize new mode values for v19: %v\n", jErr)
958
+			continue
959
+		}
960
+		tx.Set("account.channeltomodes "+account, string(newValueBytes), nil)
961
+	}
962
+
963
+	return nil
964
+}
965
+
906 966
 func getSchemaChange(initialVersion int) (result SchemaChange, ok bool) {
907 967
 	for _, change := range allChanges {
908 968
 		if initialVersion == change.InitialVersion {
@@ -998,4 +1058,9 @@ var allChanges = []SchemaChange{
998 1058
 		TargetVersion:  18,
999 1059
 		Changer:        schemaChangeV17ToV18,
1000 1060
 	},
1061
+	{
1062
+		InitialVersion: 18,
1063
+		TargetVersion:  19,
1064
+		Changer:        schemaChangeV18To19,
1065
+	},
1001 1066
 }

+ 1
- 1
irc/import.go View File

@@ -20,7 +20,7 @@ const (
20 20
 	// XXX instead of referencing, e.g., keyAccountExists, we should write in the string literal
21 21
 	// (to ensure that no matter what code changes happen elsewhere, we're still producing a
22 22
 	// db of the hardcoded version)
23
-	importDBSchemaVersion = 18
23
+	importDBSchemaVersion = 19
24 24
 )
25 25
 
26 26
 type userImport struct {

Loading…
Cancel
Save