diff --git a/go.mod b/go.mod index 7d98b995c2d1334892a3f3ea835343758b31b703..2e6d4203fab0e650603fa9a4637e77f911c723c4 100644 --- a/go.mod +++ b/go.mod @@ -18,14 +18,18 @@ require ( github.com/spf13/pflag v1.0.5 // indirect github.com/spf13/viper v1.7.1 gitlab.com/elixxir/bloomfilter v0.0.0-20200930191214-10e9ac31b228 - gitlab.com/elixxir/comms v0.0.4-0.20201125010058-1bd873622e92 - gitlab.com/elixxir/crypto v0.0.5-0.20201125005724-bcc603df02d3 + gitlab.com/elixxir/comms v0.0.4-0.20201215214310-78b71bb2bee0 + gitlab.com/elixxir/crypto v0.0.6 gitlab.com/elixxir/ekv v0.1.3 gitlab.com/elixxir/primitives v0.0.3-0.20201116174806-97f190989704 - gitlab.com/xx_network/comms v0.0.4-0.20201119231004-a67d08045535 - gitlab.com/xx_network/crypto v0.0.5-0.20201124194022-366c10b1bce0 + gitlab.com/xx_network/comms v0.0.4-0.20201215221519-b4c92324b090 + gitlab.com/xx_network/crypto v0.0.5-0.20201209162436-bc2308a94174 gitlab.com/xx_network/primitives v0.0.3-0.20201116234927-44e42fc91e7c golang.org/x/crypto v0.0.0-20201016220609-9e8e0b390897 + golang.org/x/net v0.0.0-20201110031124-69a78807bb2b // indirect + golang.org/x/sys v0.0.0-20201119102817-f84b799fce68 // indirect + google.golang.org/genproto v0.0.0-20201119123407-9b1e624d6bc4 // indirect + google.golang.org/grpc v1.33.2 // indirect google.golang.org/protobuf v1.25.0 gopkg.in/ini.v1 v1.61.0 // indirect ) diff --git a/go.sum b/go.sum index 66f26427e976ac8e1a64f5481c3c150bb76532b3..c1c049b58b05b0d006e8b00d0df681328bad89e4 100644 --- a/go.sum +++ b/go.sum @@ -252,26 +252,14 @@ github.com/zeebo/pcg v1.0.0 h1:dt+dx+HvX8g7Un32rY9XWoYnd0NmKmrIzpHF7qiTDj0= github.com/zeebo/pcg v1.0.0/go.mod h1:09F0S9iiKrwn9rlI5yjLkmrug154/YRW6KnnXVDM/l4= gitlab.com/elixxir/bloomfilter v0.0.0-20200930191214-10e9ac31b228 h1:Gi6rj4mAlK0BJIk1HIzBVMjWNjIUfstrsXC2VqLYPcA= gitlab.com/elixxir/bloomfilter v0.0.0-20200930191214-10e9ac31b228/go.mod h1:H6jztdm0k+wEV2QGK/KYA+MY9nj9Zzatux/qIvDDv3k= -gitlab.com/elixxir/comms v0.0.3 h1:7cFvBZddX/8JSY5MvfPpg21niV88IpeqQkoKs15erZM= -gitlab.com/elixxir/comms v0.0.3/go.mod h1:5p7oz4yFrK037rPap6ooaWrloJrzuVZ4jnzOdvgyqnU= -gitlab.com/elixxir/comms v0.0.4-0.20201124200043-8031463a4843 h1:KYcfQnnmc1oBAodVi3gMCXNWS6zoSCeyLhrrRzQP40Y= -gitlab.com/elixxir/comms v0.0.4-0.20201124200043-8031463a4843/go.mod h1:dRTzI+YApY9QZ2+eP9+0n5+KzxziZY24SyW31O4QWgM= -gitlab.com/elixxir/comms v0.0.4-0.20201125010058-1bd873622e92 h1:YAcb6IV0WfF2Y4jP2NRKUff9lMZmw7y07C5Ml0VIIjE= -gitlab.com/elixxir/comms v0.0.4-0.20201125010058-1bd873622e92/go.mod h1:MeyRkpCZZrMqI/uE4wfcJKZxemQfT0rqnfmYuz6HuBM= +gitlab.com/elixxir/comms v0.0.4-0.20201201195523-61ba033e1daa h1:b5F2rTq0sT5mS1VLn/ePrndQ+Zxw55l5RFfMWAphYDs= +gitlab.com/elixxir/comms v0.0.4-0.20201201195523-61ba033e1daa/go.mod h1:UhXItTZXnA284//dhxT/HYn0JQl1gLtkqg+ixPssSIA= +gitlab.com/elixxir/comms v0.0.4-0.20201215214310-78b71bb2bee0 h1:0l2HIt7Iw78j93j4qtQkNwSFon1EGI6aOQSr8FKsNiY= +gitlab.com/elixxir/comms v0.0.4-0.20201215214310-78b71bb2bee0/go.mod h1:F5wQaxr3uG2LgFrRrG/fDK8nxhpVUhHkJkNAxuWjEHw= gitlab.com/elixxir/crypto v0.0.0-20200804182833-984246dea2c4 h1:28ftZDeYEko7xptCZzeFWS1Iam95dj46TWFVVlKmw6A= gitlab.com/elixxir/crypto v0.0.0-20200804182833-984246dea2c4/go.mod h1:ucm9SFKJo+K0N2GwRRpaNr+tKXMIOVWzmyUD0SbOu2c= gitlab.com/elixxir/crypto v0.0.3 h1:znCt/x2bL4y8czTPaaFkwzdgSgW3BJc/1+dxyf1jqVw= gitlab.com/elixxir/crypto v0.0.3/go.mod h1:ZNgBOblhYToR4m8tj4cMvJ9UsJAUKq+p0gCp07WQmhA= -gitlab.com/elixxir/crypto v0.0.4 h1:8eWjvUepCU2PiqZM2NFYo6rFg1w8KWO1hMDwMNFEqoI= -gitlab.com/elixxir/crypto v0.0.4/go.mod h1:ZNgBOblhYToR4m8tj4cMvJ9UsJAUKq+p0gCp07WQmhA= -gitlab.com/elixxir/crypto v0.0.5-0.20201109234712-7e64de16970d h1:9Peb/peftTVeO5gYqi37sZycMEiu05+2VZ/j8d5lldI= -gitlab.com/elixxir/crypto v0.0.5-0.20201109234712-7e64de16970d/go.mod h1:ZNgBOblhYToR4m8tj4cMvJ9UsJAUKq+p0gCp07WQmhA= -gitlab.com/elixxir/crypto v0.0.5-0.20201124195819-54be458a0dac h1:JXtuads5nAgrSku7klahF8n+CF+dmupmm0DHsL0CCEM= -gitlab.com/elixxir/crypto v0.0.5-0.20201124195819-54be458a0dac/go.mod h1:V8lricBRpa8v1ySymXQ1/lsb+8/lSak5S7ZWRT6OACY= -gitlab.com/elixxir/crypto v0.0.5-0.20201125005532-52b3e59dddbd h1:+AmHcjwo6M5f2cbFfbJrJw822bG6Bcw6+Hl/+D2HXhg= -gitlab.com/elixxir/crypto v0.0.5-0.20201125005532-52b3e59dddbd/go.mod h1:ZNgBOblhYToR4m8tj4cMvJ9UsJAUKq+p0gCp07WQmhA= -gitlab.com/elixxir/crypto v0.0.5-0.20201125005724-bcc603df02d3 h1:TXorNuWA1udEpIlVBG2Wpd91KKYQY9Q5wXiHpgpitgM= -gitlab.com/elixxir/crypto v0.0.5-0.20201125005724-bcc603df02d3/go.mod h1:ZNgBOblhYToR4m8tj4cMvJ9UsJAUKq+p0gCp07WQmhA= gitlab.com/elixxir/crypto v0.0.6 h1:c94CGzBTV7LgInGHfmeJHrqq9nIc/WEOLUd9OeQBN74= gitlab.com/elixxir/crypto v0.0.6/go.mod h1:V8lricBRpa8v1ySymXQ1/lsb+8/lSak5S7ZWRT6OACY= gitlab.com/elixxir/ekv v0.1.3 h1:OE+LBMIhjGUMwc6hHJzYvEPNJQV7t1vMnJyIgxUMUo8= @@ -281,20 +269,25 @@ gitlab.com/elixxir/primitives v0.0.0-20200804170709-a1896d262cd9/go.mod h1:p0Vel gitlab.com/elixxir/primitives v0.0.0-20200804182913-788f47bded40/go.mod h1:tzdFFvb1ESmuTCOl1z6+yf6oAICDxH2NPUemVgoNLxc= gitlab.com/elixxir/primitives v0.0.1 h1:q61anawANlNAExfkeQEE1NCsNih6vNV1FFLoUQX6txQ= gitlab.com/elixxir/primitives v0.0.1/go.mod h1:kNp47yPqja2lHSiS4DddTvFpB/4D9dB2YKnw5c+LJCE= -gitlab.com/elixxir/primitives v0.0.2 h1:PvyOOp/A6tCtmU7YnGhCCPRdmEogEzCi0Li/WfiVjGo= -gitlab.com/elixxir/primitives v0.0.2/go.mod h1:3fxFHSlQhkV4vs+S0dZEz3Om3m+40WX8L806yvSnNFc= gitlab.com/elixxir/primitives v0.0.3-0.20201116174806-97f190989704 h1:JkFREumz8skDqkCjjzZnlf5tg+PBiMB9kfVn9z0VEfE= gitlab.com/elixxir/primitives v0.0.3-0.20201116174806-97f190989704/go.mod h1:3fxFHSlQhkV4vs+S0dZEz3Om3m+40WX8L806yvSnNFc= gitlab.com/xx_network/comms v0.0.0-20200805174823-841427dd5023/go.mod h1:owEcxTRl7gsoM8c3RQ5KAm5GstxrJp5tn+6JfQ4z5Hw= -gitlab.com/xx_network/comms v0.0.3 h1:ch1eJI4WXUE/Kz0Kp9uDWX16B+hfVFmdHY+EOai4Wzc= -gitlab.com/xx_network/comms v0.0.3/go.mod h1:YViGbRj7FjJYoaO4NpALGEd9dK/l8uUT000FEBbUTL8= gitlab.com/xx_network/comms v0.0.4-0.20201119231004-a67d08045535 h1:3KoNUndePTAUMlX1xc+zk0wuOZMb/xJMUVuhS+HisdA= gitlab.com/xx_network/comms v0.0.4-0.20201119231004-a67d08045535/go.mod h1:YViGbRj7FjJYoaO4NpALGEd9dK/l8uUT000FEBbUTL8= +gitlab.com/xx_network/comms v0.0.4-0.20201130190834-365ddae56e7b/go.mod h1:YViGbRj7FjJYoaO4NpALGEd9dK/l8uUT000FEBbUTL8= +gitlab.com/xx_network/comms v0.0.4-0.20201202184223-c22375bd1e6d/go.mod h1:YViGbRj7FjJYoaO4NpALGEd9dK/l8uUT000FEBbUTL8= +gitlab.com/xx_network/comms v0.0.4-0.20201203181401-3e7646e39ffd h1:rbk0gz/cRsMBvZ3SC59XgGdUIFym2W0lpitlykcCWdk= +gitlab.com/xx_network/comms v0.0.4-0.20201203181401-3e7646e39ffd/go.mod h1:YViGbRj7FjJYoaO4NpALGEd9dK/l8uUT000FEBbUTL8= +gitlab.com/xx_network/comms v0.0.4-0.20201215221519-b4c92324b090 h1:7J8iMiX7B6tNwbinP00GIARZy+O0L9P0IM8KcxXMK8g= +gitlab.com/xx_network/comms v0.0.4-0.20201215221519-b4c92324b090/go.mod h1:YViGbRj7FjJYoaO4NpALGEd9dK/l8uUT000FEBbUTL8= gitlab.com/xx_network/crypto v0.0.3/go.mod h1:DF2HYvvCw9wkBybXcXAgQMzX+MiGbFPjwt3t17VRqRE= gitlab.com/xx_network/crypto v0.0.4 h1:lpKOL5mTJ2awWMfgBy30oD/UvJVrWZzUimSHlOdZZxo= gitlab.com/xx_network/crypto v0.0.4/go.mod h1:+lcQEy+Th4eswFgQDwT0EXKp4AXrlubxalwQFH5O0Mk= gitlab.com/xx_network/crypto v0.0.5-0.20201124194022-366c10b1bce0 h1:v2xX/bl9lyZJZXXFZ6glDs7F/GNGIeKAH6hzafUNi5w= gitlab.com/xx_network/crypto v0.0.5-0.20201124194022-366c10b1bce0/go.mod h1:+lcQEy+Th4eswFgQDwT0EXKp4AXrlubxalwQFH5O0Mk= +gitlab.com/xx_network/crypto v0.0.5-0.20201203175549-582fde7fcbe1/go.mod h1:NM4Lk3//mOSlWwySpaH8FMmYZNm8qtjr6EawfaAHzH4= +gitlab.com/xx_network/crypto v0.0.5-0.20201209162436-bc2308a94174 h1:KpVvbYTWFpEz7MgzbG3YzIcOsNQrUBCCLwRDC2sDqv8= +gitlab.com/xx_network/crypto v0.0.5-0.20201209162436-bc2308a94174/go.mod h1:NM4Lk3//mOSlWwySpaH8FMmYZNm8qtjr6EawfaAHzH4= gitlab.com/xx_network/primitives v0.0.0-20200803231956-9b192c57ea7c/go.mod h1:wtdCMr7DPePz9qwctNoAUzZtbOSHSedcK++3Df3psjA= gitlab.com/xx_network/primitives v0.0.0-20200804183002-f99f7a7284da h1:CCVslUwNC7Ul7NG5nu3ThGTSVUt1TxNRX+47f5TUwnk= gitlab.com/xx_network/primitives v0.0.0-20200804183002-f99f7a7284da/go.mod h1:OK9xevzWCaPO7b1wiluVJGk7R5ZsuC7pHY5hteZFQug= @@ -360,8 +353,9 @@ golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200707034311-ab3426394381 h1:VXak5I6aEWmAXeQjA+QSZzlgNrpq9mjcfDemuexIKsU= golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= -golang.org/x/net v0.0.0-20201029221708-28c70e62bb1d h1:dOiJ2n2cMwGLce/74I/QHMbnpk5GfY7InR8rczoMqRM= golang.org/x/net v0.0.0-20201029221708-28c70e62bb1d/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= +golang.org/x/net v0.0.0-20201110031124-69a78807bb2b h1:uwuIcX0g4Yl1NC5XAz37xsr2lTtcqevgzYNVt49waME= +golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= @@ -388,8 +382,9 @@ golang.org/x/sys v0.0.0-20200519105757-fe76b779f299 h1:DYfZAGf2WMFjMxbgTjaC+2HC7 golang.org/x/sys v0.0.0-20200519105757-fe76b779f299/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200917073148-efd3b9a0ff20/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20201029080932-201ba4db2418 h1:HlFl4V6pEMziuLXyRkm5BIYq1y1GAbb02pRlWvI54OM= golang.org/x/sys v0.0.0-20201029080932-201ba4db2418/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20201119102817-f84b799fce68 h1:nxC68pudNYkKU6jWhgrqdreuFiOQWj1Fs7T3VrH4Pjw= +golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= @@ -439,8 +434,9 @@ google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98 google.golang.org/genproto v0.0.0-20190911173649-1774047e7e51/go.mod h1:IbNlFCBrqXvoKpeg0TB2l7cyZUmoaFKYIwrEpbDKLA8= google.golang.org/genproto v0.0.0-20191108220845-16a3f7862a1a/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= -google.golang.org/genproto v0.0.0-20201030142918-24207fddd1c3 h1:sg8vLDNIxFPHTchfhH1E3AI32BL3f23oie38xUWnJM8= google.golang.org/genproto v0.0.0-20201030142918-24207fddd1c3/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20201119123407-9b1e624d6bc4 h1:Rt0FRalMgdSlXAVJvX4pr65KfqaxHXSLkSJRD9pw6g0= +google.golang.org/genproto v0.0.0-20201119123407-9b1e624d6bc4/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= diff --git a/storage/conversation/partner.go b/storage/conversation/partner.go index 291dcbe7866e9ae13f0ba7d4d7f7c248c7a50de8..50650a1acd25dbe7812115efcc755ad9eae4e952 100644 --- a/storage/conversation/partner.go +++ b/storage/conversation/partner.go @@ -27,33 +27,35 @@ const ( ) type Conversation struct { - // Public & stored data + // Public and stored data lastReceivedID uint32 numReceivedRevolutions uint32 nextSentID uint64 - // Private, unstored data + // Private and non-stored data partner *id.ID kv *versioned.KV mux sync.Mutex } +// conversationDisk stores the public data of Conversation for saving to disk. type conversationDisk struct { - // Public & stored data + // Public and stored data LastReceivedID uint32 NumReceivedRevolutions uint32 NextSendID uint64 } -// LoadOrMakeConversation returns the Conversation if it can be found, otherwise -// returns a new partner. +// LoadOrMakeConversation returns the Conversation with the given ID, if it can +// be found in KV. Otherwise, a new conversation with the given ID is generated, +// saved to KV, and returned. func LoadOrMakeConversation(kv *versioned.KV, partner *id.ID) *Conversation { - c, err := loadConversation(kv, partner) if err != nil && !strings.Contains(err.Error(), "Failed to Load conversation") { jww.FATAL.Panicf("Failed to loadOrMakeConversation: %s", err) } + // Create new conversation and save to KV if one does not exist if c == nil { c = &Conversation{ lastReceivedID: 0, @@ -62,6 +64,7 @@ func LoadOrMakeConversation(kv *versioned.KV, partner *id.ID) *Conversation { partner: partner, kv: kv, } + if err = c.save(); err != nil { jww.FATAL.Panicf("Failed to save new conversation: %s", err) } @@ -86,6 +89,7 @@ func (c *Conversation) ProcessReceivedMessageID(mid uint32) uint64 { "Received ID in a conversation: %s", err) } high = c.numReceivedRevolutions + case 0: if mid > c.lastReceivedID { c.lastReceivedID = mid @@ -95,6 +99,7 @@ func (c *Conversation) ProcessReceivedMessageID(mid uint32) uint64 { } } high = c.numReceivedRevolutions + case -1: high = c.numReceivedRevolutions - 1 } @@ -124,6 +129,7 @@ func (c *Conversation) GetNextSendID() (uint64, uint32) { return old, uint32(old & 0x00000000FFFFFFFF) } +// loadConversation returns the Conversation with the given ID from KV storage. func loadConversation(kv *versioned.KV, partner *id.ID) (*Conversation, error) { key := makeConversationKey(partner) @@ -144,6 +150,7 @@ func loadConversation(kv *versioned.KV, partner *id.ID) (*Conversation, error) { return c, nil } +// save saves the Conversation to KV storage. func (c *Conversation) save() error { data, err := c.marshal() if err != nil { @@ -160,6 +167,12 @@ func (c *Conversation) save() error { return c.kv.Set(key, &obj) } +// delete removes the Conversation from KV storage. +func (c *Conversation) delete() error { + key := makeConversationKey(c.partner) + return c.kv.Delete(key) +} + func (c *Conversation) unmarshal(b []byte) error { cd := conversationDisk{} diff --git a/storage/conversation/partner_test.go b/storage/conversation/partner_test.go index 1be213ede66e6974ad7db526cdf8c11f99479668..b2381e77bf6ced1f871c949d79bc59fb943e2680 100644 --- a/storage/conversation/partner_test.go +++ b/storage/conversation/partner_test.go @@ -185,6 +185,29 @@ func TestConversation_save_load(t *testing.T) { } } +// Happy path. +func TestConversation_Delete(t *testing.T) { + kv := versioned.NewKV(make(ekv.Memstore)) + partner := id.NewIdFromString("partner ID", id.User, t) + conv := makeRandomConv(kv, partner) + + if err := conv.save(); err != nil { + t.Fatalf("Failed to save conversation to storage: %+v", err) + } + + if _, err := loadConversation(kv, partner); err != nil { + t.Fatalf("Failed to load conversation from storage: %v", err) + } + + if err := conv.delete(); err != nil { + t.Errorf("delete() produced an error: %+v", err) + } + + if _, err := loadConversation(kv, partner); err == nil { + t.Error("Object found in storage when it should be deleted.") + } +} + // Tests the happy path of marshal() and unmarshal(). func TestConversation_marshal_unmarshal(t *testing.T) { expectedConv := makeRandomConv(versioned.NewKV(make(ekv.Memstore)), diff --git a/storage/conversation/store.go b/storage/conversation/store.go index 3f39461e814af0f73e9c8c3463d2d67b8a2f99e7..9e6dfae045bed7339efcc357a9f5b35f3352f64a 100644 --- a/storage/conversation/store.go +++ b/storage/conversation/store.go @@ -8,6 +8,7 @@ package conversation import ( + jww "github.com/spf13/jwalterweatherman" "gitlab.com/elixxir/client/storage/versioned" "gitlab.com/xx_network/primitives/id" "sync" @@ -21,7 +22,7 @@ type Store struct { mux sync.RWMutex } -//Returns a new conversation store made off of the KV +// NewStore returns a new conversation store made off of the KV. func NewStore(kv *versioned.KV) *Store { kv = kv.Prefix(conversationKeyPrefix) return &Store{ @@ -30,12 +31,13 @@ func NewStore(kv *versioned.KV) *Store { } } -// Gets the conversation with the partner from ram if it is there, otherwise -// loads it from disk +// Get gets the conversation with the given partner ID from RAM, if it is there. +// Otherwise, it loads it from disk. func (s *Store) Get(partner *id.ID) *Conversation { s.mux.RLock() c, ok := s.loadedConversations[*partner] s.mux.RUnlock() + if !ok { s.mux.Lock() c, ok = s.loadedConversations[*partner] @@ -47,3 +49,26 @@ func (s *Store) Get(partner *id.ID) *Conversation { } return c } + +// Delete deletes the conversation with the given partner ID from memory and +// storage. Panics if the object cannot be deleted from storage. +func (s *Store) Delete(partner *id.ID) { + s.mux.Lock() + defer s.mux.Unlock() + + // Get contact from memory + c, exists := s.loadedConversations[*partner] + if !exists { + return + } + + // Delete contact from storage + err := c.delete() + if err != nil { + jww.FATAL.Panicf("Failed to remover conversation with ID %s from "+ + "storage: %+v", partner, err) + } + + // Delete contact from memory + delete(s.loadedConversations, *partner) +} diff --git a/storage/conversation/store_test.go b/storage/conversation/store_test.go index e88b5bec032f626e934e19c0257f19466b93f80f..fe9882af5f2050f15596e9c721cb9281922684df 100644 --- a/storage/conversation/store_test.go +++ b/storage/conversation/store_test.go @@ -12,6 +12,7 @@ import ( "gitlab.com/elixxir/client/storage/versioned" "gitlab.com/elixxir/ekv" "gitlab.com/xx_network/primitives/id" + "math/rand" "testing" ) @@ -26,3 +27,39 @@ func TestStore_Get_Prefix(t *testing.T) { conv := store.Get(id.NewIdFromUInt(8, id.User, t)) t.Log(conv) } + +// Happy path. +func TestStore_Delete(t *testing.T) { + kv := versioned.NewKV(make(ekv.Memstore)) + store := NewStore(kv) + pids := make([]*id.ID, 10) + + // Generate list of IDs + for i := range pids { + pids[i] = id.NewIdFromUInt(rand.Uint64(), id.User, t) + } + + // Add IDs to storage and memory + for _, pid := range pids { + store.Get(pid) + } + + // Delete conversations with IDs with even numbered indexes + for i := 0; i < len(pids); i += 2 { + store.Delete(pids[i]) + } + + // Ensure even numbered conversation were deleted and all others still exist + for i, pid := range pids { + _, exists := store.loadedConversations[*pid] + if i%2 == 0 { + if exists { + t.Errorf("%d. Delete() failed to delete the conversation "+ + "(ID %s) from memory.", i, pid) + } + } else if !exists { + t.Errorf("%d. Delete() unexpetedly deleted the conversation "+ + "(ID %s) from memory.", i, pid) + } + } +}