Help Request: Strange BoltDB Bug, Can't Find!

blov · · 628 次点击    
这是一个分享于 的资源,其中的信息可能已经有所发展或是发生改变。
<p><strong>edit</strong>: Thanks to <a href="https://github.com/takching">takching</a> and <a href="/u/korylprince">/u/korylprince</a> for helping me fix this. I&#39;m pleased to say that <a href="https://github.com/cathalgarvey/listless">listless</a> now basically works, allowing you to host a simple discussion list using any IMAP/SMTP account, instead of relying on Google, Yahoo, or maintaining your own email stack just to run Mailman. :)</p> <hr/> <p>Hi all,</p> <p>Not normally one to post for help without really trying to fix first by myself, but I&#39;m at wits end.</p> <p>I&#39;m working on a project right now <a href="https://github.com/cathalgarvey/listless">to permit people to host email discussion lists using only IMAP/SMTP</a>: In fact, I found it very strange that nobody else seems to have done this already. The basic architecture is: Config file with account details, and a lua script to run on any incoming mail which does the work of handling, storing, modifying, and dispatching mail. Indeed, you could use this to write a Lua-scripted email bot that has nothing to do with a discussion list or mailing list, but that&#39;s not the primary goal.</p> <p>For this project, I chose to use [bolt as the database backend](github.com/boltdb/bolt), which currently is only being written to store list archives (optionally, as scripted in the Lua bits) and to store/access/modify list members/subscribers&#39; entries.</p> <p>The problem I&#39;m having is that when adding users to the database, the first user is entered OK, but subsequent users&#39; values clobber them.</p> <p>That is, each call (in lua) to <code>database:UpdateSubscriber(&#34;foo@bar.com&#34;, foometa)</code> calls a <code>db.Update(func(tx *bolt.Tx) error { ... })</code> method where foometa is JSON marshalled and entered into a bucket called &#34;members&#34;. The first such call leads to a database bucket like this:</p> <pre><code>members: { foo@bar.com: { name: Foo email: foo@bar.com moderator: false } } </code></pre> <p>..But the second call, with a different user email and meta object (created independently, that is) with different values, say <code>database:UpdateSubscriber(&#34;baz@qux.com&#34;, bazmeta)</code>, (where baz is a mod) leads to this:</p> <pre><code>members: { foo@bar.com: { name: Baz email: baz@qux.com moderator: true } baz@qux.com: { name: Baz email: baz@qux.com moderator: true } </code></pre> <p>I&#39;m <strong>not</strong> using global variables for this part of my code, nor is there any scope leakage I&#39;m aware of, or ambiguous variable naming, etcetera etcetera. I was wary of some shenanigans in the Lua layer so I rewrote some of the database methods/bindings and instantiated my foos/bazzes separately to be sure. The problem persists.</p> <p>This is very basic boltdb usage, which is what prompts me to write it here; either someone else has encountered this before, or it&#39;s undocumented, or I&#39;m just an idiot. Any of the three should be suitable entertaining for others here, methinks.</p> <p>It&#39;s a big ask, but if anyone feels like helping, <a href="https://github.com/cathalgarvey/listless/issues/2">I documented the bug and how to reproduce on the project issue tracker</a>. I&#39;d sincerely like to learn what&#39;s going awry here! This bug may be one of the last things stopping this project from working overall in a basic way so I&#39;m keen to squash it.</p> <p>Big thanks for any insight ye can offer!</p> <hr/>**评论:**<br/><br/>korylprince: <pre><pre><code>diff --git a/database.go b/database.go index cf712b4..575f759 100644 --- a/database.go +++ b/database.go @@ -217,7 +217,7 @@ func (db *ListlessDB) goGetAllSubscribers(modsOnly bool) (subscribers []string) db.View(func(tx *bolt.Tx) error { members := tx.Bucket([]byte(&#34;members&#34;)) c := members.Cursor() - for email, metabytes := c.First(); email != nil; email, _ = c.Next() { + for email, metabytes := c.First(); email != nil; email, metabytes = c.Next() { log.Printf(&#34;Iterating over database member: %s, meta: %s&#34;, email, string(metabytes)) meta := MemberMeta{} err := json.Unmarshal(metabytes, &amp;meta) </code></pre> <p>After debugging for about 45 minutes, it came to this. I knew your boltdb code was fine. You were just using the <code>metabytes</code> from <code>c.First()</code> instead of updating it on each iteration. Fun problem!</p></pre>anacrolix: <pre><p>Fix my bugs plz</p></pre>cathalgarvey: <pre><p>OMG thank you! I had been meaning to switch to ForEach anyway..</p> <p>That&#39;s a subtle and irritating bug, I wasn&#39;t even looking there for the source!</p></pre>jayposs: <pre><p>Can&#39;t explain your results, but are you converting the key from a string to a byte slice, []byte(key) ?</p></pre>

入群交流(和以上内容无关):加入Go大咖交流群,或添加微信:liuxiaoyan-s 备注:入群;或加QQ群:692541889

628 次点击  
加入收藏 微博
暂无回复
添加一条新回复 (您需要 登录 后才能回复 没有账号 ?)
  • 请尽量让自己的回复能够对别人有帮助
  • 支持 Markdown 格式, **粗体**、~~删除线~~、`单行代码`
  • 支持 @ 本站用户;支持表情(输入 : 提示),见 Emoji cheat sheet
  • 图片支持拖拽、截图粘贴等方式上传