go版本CentOS 7,go版本go1.17.7 linux/amd64 64
这个问题可能会导致对BoltDB工作方式的误解,或者我有一个bug,或者有一个问题。我以前使用过BoltDB,并取得了很好的效果。不过,我并没有明确地找出这个问题。我看到的是,我尝试从桶中删除一个键,并且在active db.Update中删除密钥及其值,但是在db.Update结束后它仍然存在。寻找可能发生的事情的任何解释。看来这个功能不可能被破坏。
我使用一个BoltDB桶来存储与创建新帐户的电子邮件地址相关的临时令牌。希望立即整理和清理旧数据(过期的令牌、误用的令牌等)。相当标准的东西。临时令牌的结构是(键是临时令牌,10位随机字符串):
(临时令牌是桶键)
type tempTokenStruct struct {
EmailAddress string `json:"emailaddress"` // Email Address to be changed
TokenExpiryTime int64 `json:"tokenexpirytime"` // Expiry Time for token in Epoch time
}用户在web表单中输入电子邮件地址并点击“submit”。这将创建对REST服务的调用,该调用将在临时令牌表中创建一个条目,如下所示:
"BpLnfgDsc2“=> foo@bar.com,1645650084
该服务发送电子邮件给具有临时令牌嵌入的URL,该链接将用户带到允许他们输入电子邮件地址(再次验证)和新密码(两次)的表单。然后,点击Submit就会从web处理程序中调用以下代码:
func checkTokenValid(emailAddress string, tempToken string) error {
var tempTokenData tempTokenStruct
var tempTokenBytes []byte
tempTokenBytes = []byte(tempToken)
db, err := bolt.Open(USER_DB_NAME, 0644, nil)
if err != nil {
return err
}
defer db.Close()
err = db.Update(func(tx *bolt.Tx) error {
tempTokenBucket := tx.Bucket([]byte("temptokens"))
// The bucket hasn't been created, so there are no stored tokens
if tempTokenBucket == nil {
return errors.New("Not Authorized (1): Please request a new password new/change email from the login page.")
}
// There is no matching token stored in the bucket, so this is an invalid request
tempTokenJSON := tempTokenBucket.Get(tempTokenBytes)
//[I've put a printf here: A]
if tempTokenJSON == nil {
return errors.New("Not Authorized (2): Please request a new password new/change email from the login page.")
}
jsonConvertErr := json.Unmarshal(tempTokenJSON, &tempTokenData)
if jsonConvertErr != nil {
tempTokenBucket.Delete(tempTokenBytes)
return errors.New("Not Authorized (3): Please request a new password new/change email from the login page.")
}
// Check to see if the time is expired, if so, remove the key and indicate error
if tempTokenData.TokenExpiryTime < time.Now().Unix() {
tempTokenBucket.Delete(tempTokenBytes)
//[I've put a printf here: B]
return errors.New("Not Authorized (4): Please request a new password new/change email from the login page.")
}
// Check to see if the email addresses match
if emailAddress != tempTokenData.EmailAddress {
tempTokenBucket.Delete(tempTokenBytes)
return errors.New("Not Authorized (5): Please request a new password new/change email from the login page.")
}
tempTokenBucket.Delete(tempTokenBytes)
return nil
})
// This is test code to see if the key was in fact deleted
db.Update(func(tx *bolt.Tx) error {
tempTokenBucket := tx.Bucket([]byte("temptokens"))
tempTokenJSON := tempTokenBucket.Get(tempTokenBytes)
// [I've put a printf here: C]
return nil
})
return err
}我正在用一个超时令牌(4)进行测试,所以当它遇到超时令牌时,它想要从桶中删除这个现在无效的令牌。
在A位置,它打印:第一个Get调用令牌BpLnfgDsc2是{"emailaddress":"foo@bar.com","tokenexpirytime":1645650084}
在我将代码放在执行.Get的B位置,它打印出来(看起来要删除):在DB关闭(4)之前,删除之后,令牌BpLnfgDsc2是
在C位置,它打印(看起来是返回):在DB关闭后,令牌BpLnfgDsc2是{"emailaddress":"foo@bar.com","tokenexpirytime":1645650084}
任何内容都不返回错误。我已经重复了很多次,把fmt.Printfs放在任何地方,看看到底是怎么回事。结果是一样的,关键似乎没有被删除。在此之后,我将对DB文件进行'vi -b‘,而键,值仍然存在。运行后,它仍然看到关键的值在那里。我很困惑,任何建议都会很感激的。
更新: Put/Get/Delete/Get的基本螺栓功能按照此测试代码工作(应该是显而易见的):
package main
import "fmt"
import "encoding/json"
import "github.com/boltdb/bolt"
type tempTokenStruct struct {
EmailAddress string `json:"emailaddress"` // Email Address to be changed (Temporary Token is the DB key)
TokenExpiryTime int64 `json:"tokenexpirytime"` // Expiry Time for token in Epoch time
}
func main() {
var tempToken tempTokenStruct
tempToken.EmailAddress = "foo@bar.com"
tempToken.TokenExpiryTime = 1234567890
tempTokenDataJSON, jsonMarshalError := json.Marshal(tempToken)
if jsonMarshalError != nil {
fmt.Printf("JSON Marshal Error: %s\n", jsonMarshalError.Error())
return
}
tempTokenKey := []byte("foo")
db, err := bolt.Open("test.db", 0644, nil)
if err != nil {
fmt.Printf("Error opening Database\n")
return
}
defer db.Close()
// Put a key in the table
err = db.Update(func(tx *bolt.Tx) error {
tempTokenBucket, err := tx.CreateBucketIfNotExists([]byte("temptokens"))
if err != nil {
return err
}
dbPutError := tempTokenBucket.Put(tempTokenKey, []byte(tempTokenDataJSON))
return dbPutError
})
if err != nil {
fmt.Printf("Error putting key value pair into table: %s\n", err.Error())
}
// Check if the key/value is there after putting it in
err = db.Update(func(tx *bolt.Tx) error {
tempTokenBucket, err := tx.CreateBucketIfNotExists([]byte("temptokens"))
if err != nil {
return err
}
valueGet := tempTokenBucket.Get(tempTokenKey)
fmt.Printf("Value for Token: \"%s\" is \"%s\" just after putting it in there\n", tempTokenKey, valueGet)
return nil
})
// Delete that key from the table
err = db.Update(func(tx *bolt.Tx) error {
tempTokenBucket, err := tx.CreateBucketIfNotExists([]byte("temptokens"))
if err != nil {
return err
}
dbDeleteError := tempTokenBucket.Delete(tempTokenKey)
return dbDeleteError
})
if err != nil {
fmt.Printf("Error Deleting key from bucket: %s\n", err.Error())
}
// Check if the key/value is there after deleting it
err = db.Update(func(tx *bolt.Tx) error {
tempTokenBucket, err := tx.CreateBucketIfNotExists([]byte("temptokens"))
if err != nil {
return err
}
valueGet := tempTokenBucket.Get(tempTokenKey)
fmt.Printf("Value for Token: \"%s\" is \"%s\" after the delete\n", tempTokenKey, valueGet)
return nil
})
if err != nil {
fmt.Printf("Error getting key from table: %s\n", err.Error())
}
}打印出来:
令牌的值:"foo“是"{"emailaddress":"foo@bar.com","tokenexpirytime":1234567890}”就在把它放在那里之后
值:删除后的"foo“是"”。
所以,不知道为什么其他代码不能工作。好像delete使用的是不同的键,但是其他代码的键是相同的。
发布于 2022-02-24 04:45:53
我认为具有非零返回值的db.Update的行为是这里的混乱。根据医生们
在闭包中,您有一个一致的数据库视图。通过在结束时返回零来提交事务。还可以通过返回错误在任何时候回滚事务。
您将返回一个错误:
return errors.New("Not Authorized (4): Please request a new password new/change email from the login page.")这意味着该db.Update(中的所有操作都回滚。这可以在简单的示例中通过一个小的更改(return fmt.Errorf("RETURNING ERROR HERE"))来复制:
package main
import "fmt"
import "encoding/json"
import "github.com/boltdb/bolt"
type tempTokenStruct struct {
EmailAddress string `json:"emailaddress"` // Email Address to be changed (Temporary Token is the DB key)
TokenExpiryTime int64 `json:"tokenexpirytime"` // Expiry Time for token in Epoch time
}
func main() {
var tempToken tempTokenStruct
tempToken.EmailAddress = "foo@bar.com"
tempToken.TokenExpiryTime = 1234567890
tempTokenDataJSON, jsonMarshalError := json.Marshal(tempToken)
if jsonMarshalError != nil {
fmt.Printf("JSON Marshal Error: %s\n", jsonMarshalError.Error())
return
}
tempTokenKey := []byte("foo")
db, err := bolt.Open("test.db", 0644, nil)
if err != nil {
fmt.Printf("Error opening Database\n")
return
}
defer db.Close()
// Put a key in the table
err = db.Update(func(tx *bolt.Tx) error {
tempTokenBucket, err := tx.CreateBucketIfNotExists([]byte("temptokens"))
if err != nil {
return err
}
dbPutError := tempTokenBucket.Put(tempTokenKey, []byte(tempTokenDataJSON))
return dbPutError
})
if err != nil {
fmt.Printf("Error putting key value pair into table: %s\n", err.Error())
}
// Check if the key/value is there after putting it in
err = db.Update(func(tx *bolt.Tx) error {
tempTokenBucket, err := tx.CreateBucketIfNotExists([]byte("temptokens"))
if err != nil {
return err
}
valueGet := tempTokenBucket.Get(tempTokenKey)
fmt.Printf("Value for Token: \"%s\" is \"%s\" just after putting it in there\n", tempTokenKey, valueGet)
return nil
})
// Delete that key from the table
err = db.Update(func(tx *bolt.Tx) error {
tempTokenBucket, err := tx.CreateBucketIfNotExists([]byte("temptokens"))
if err != nil {
return err
}
tempTokenBucket.Delete(tempTokenKey)
return fmt.Errorf("RETURNING ERROR HERE") // CHANGED HERE
})
if err != nil {
fmt.Printf("Error Deleting key from bucket: %s\n", err.Error())
}
// Check if the key/value is there after deleting it
err = db.Update(func(tx *bolt.Tx) error {
tempTokenBucket, err := tx.CreateBucketIfNotExists([]byte("temptokens"))
if err != nil {
return err
}
valueGet := tempTokenBucket.Get(tempTokenKey)
fmt.Printf("Value for Token: \"%s\" is \"%s\" after the delete\n", tempTokenKey, valueGet)
return nil
})
if err != nil {
fmt.Printf("Error getting key from table: %s\n", err.Error())
}
}现在的产出是:
Value for Token: "foo" is "{"emailaddress":"foo@bar.com","tokenexpirytime":1234567890}" just after putting it in there
Error Deleting key from bucket: RETURNING ERROR HERE
Value for Token: "foo" is "{"emailaddress":"foo@bar.com","tokenexpirytime":1234567890}" after the delete这似乎与您在主代码中看到的内容相匹配。修复相对简单--如果您希望提交更改,请不要返回错误。
https://stackoverflow.com/questions/71246379
复制相似问题