Further to a previous topic on best practice for attachment handling…
I’ve had a long standing issue with attachments and have finally been able to reduce it to a small code fragment and a set of steps to reproduce. I’m hoping that I’ve done something stupid here - so any pointers would be gratefully accepted.
Here’s the procedure to reproduce the problem (note this is using Xamarin on the mac - with everything up to date).
- Create a new Mac Cocoa App
- In Project Options | Build | General, change the Target Framework to “Xamarin.Mac .Net 4.5 Framework”.
- Use “Add Packages…” to add Couchbase.Lite, latest (1.4.0) version.
- Add the following test function to the end of ViewController class in ViewController.cs (see below).
- Add the following line to the end of ViewDidLoad in ViewController.cs.
RunTest();
- Add the following lines to the top of ViewController.cs:
using Couchbase.Lite;
using System.Linq;
- Set as Startup Project
- Run | Start Debugging.
It will work the first time. Quit the app and run again. It will fail.
Some notes:
-
The issue only happens when debugging - if I run without debugging it works fine.
-
The issue occurs with 1.3.1 and 1.4.0 of couchbase.lite (I’ve tried both).
-
You can simply change the attachment a little to generate a new SHA-1 hash (and therefore new filename). It will run once then fail again.
-
I’ve checked the database after a successful insertion - the record looks fine, and includes the attachment.
-
I’ve checked the permissions on the attachments folder underneath testdb.cblite2 - they look ok:
drwxr-xr-x 5 Paul staff 170 4 May 13:23 attachments
Here is the test function:
private void RunTest()
{
// Create a database in the default location (~/.local/share)
var dbo = new DatabaseOptions();
dbo.Create = true;
var db = Manager.SharedInstance.OpenDatabase("testdb", dbo);
// Create the document with a unique ID
var id = Guid.NewGuid().ToString("N");
Console.WriteLine("Creating id {0}", id);
var doc = db.GetDocument(id);
// Create a revision of the document...
var rev = doc.CreateRevision();
if (rev == null)
throw new Exception("Unable to create revision");
// Set some properties
var props = rev.Properties;
props["name"] = "This is my name";
props["number"] = 27;
rev.SetProperties(props);
// Create some data for an attachment
byte[] data = Enumerable.Repeat((byte)0x05, 1024).ToArray();
// Change one byte to modify the SHA hash (and therefore the attachment file name)
// data[0] = (byte)2; // this makes the code work ONCE
rev.SetAttachment("blob", "application/octet-stream", data);
rev.Save();
}