Git Product home page Git Product logo

cdtdatastore's Introduction

⚠️ NO LONGER MAINTAINED ⚠️

This library is end-of-life and no longer supported.

This repository will not be updated. The repository will be kept available in read-only mode. If you are interested in continuing development efforts please see the list of forks for alternatives (e.g. #465).

For FAQs and additional information please refer to the Cloudant blog.

CDTDatastore

Version Platform Build Status

Applications use Cloudant Sync to store, index and query local JSON data on a device and to synchronise data between many devices. Synchronisation is under the control of the application, rather than being controlled by the underlying system. Conflicts are also easy to manage and resolve, either on the local device or in the remote database.

Cloudant Sync is an Apache CouchDB™ replication-protocol-compatible datastore for devices that don't want or need to run a full CouchDB instance. It's built by Cloudant, building on the work of many others, and is available under the Apache 2.0 licence.

The API is quite different from CouchDB's; we retain the MVCC data model but not the HTTP-centric API.

This library is for iOS, an Android version is also available.

If you have questions, please join our mailing list and drop us a line.

Using in your project

CDTDatastore is available through CocoaPods, to install it add the following line to your Podfile:

pod "CDTDatastore"

Note: We only support building on the latest stable release of Xcode

Using in a Swift app

CDTDatastore is useable from Swift out of the box with a few small quirks. Install as per the instructions above, and import CloudantSync.h into your bridging header.

The Overview section below has examples in both Objective-C and Swift.

Example project

There is an example project in the Project folder, for iOS 8.0. To get this up and running independently of the main codebase, a Podfile is included:

$ cd Project
$ pod install
$ open Project.xcworkspace

In order to run the sample project, edit the URL defined in CDTViewController.m: in replicatorURL. Change this to the credentials for your own account and database, ensuring you have _reader, _writer, and _replicator permissions.

Once running you will be able to edit "to-do" items in the app and in your Cloudant database and replicate these changes in both directions.

Running the tests

See CONTRIBUTING.

Tested Platforms

CDTDatastore gets regularly tested on the following platforms:

  • OS X 10.11 (El Captain)
  • iPhone 4S (Simulator), iOS 9.2

Overview of the library

Once the libraries are added to a project, the basics of adding and reading a document are:

#import <CloudantSync.h>

// Create a CDTDatastoreManager using application internal storage path
NSError *outError = nil;
NSFileManager *fileManager= [NSFileManager defaultManager];

NSURL *documentsDir = [[fileManager URLsForDirectory:NSDocumentDirectory
                                           inDomains:NSUserDomainMask] lastObject];
NSURL *storeURL = [documentsDir URLByAppendingPathComponent:@"cloudant-sync-datastore"];
NSString *path = [storeURL path];

CDTDatastoreManager *manager =
[[CDTDatastoreManager alloc] initWithDirectory:path
                                         error:&outError];

CDTDatastore *datastore = [manager datastoreNamed:@"my_datastore"
                                            error:&outError];

// Create a document
CDTDocumentRevision *rev = [CDTDocumentRevision revisionWithDocId:@"doc1"];
// Use [CDTDocumentRevision revision] to get an ID generated for you on saving
rev.body = [@{
    @"description": @"Buy milk",
    @"completed": @NO,
    @"type": @"com.cloudant.sync.example.task"
} mutableCopy];

// Add an attachment -- binary data like a JPEG
CDTUnsavedFileAttachment *att1 = [[CDTUnsavedFileAttachment alloc]
                          initWithPath:@"/path/to/image.jpg"
                          name:@"cute_cat.jpg"
                          type:@"image/jpeg"];
rev.attachments[att1.name] = att;

// Save the document to the database
CDTDocumentRevision *revision = [datastore createDocumentFromRevision:rev
                                                                error:&error];
// `revision` will be `nil` on failures.

// Read a document
NSString *docId = revision.docId;
CDTDocumentRevision *retrieved = [datastore getDocumentWithId:docId
                                                        error:&error];

If you are using Swift, install the library as per the instructions above and add the use_frameworks! instruction to your target. A bridging header is required if the use_frameworks! instruction is not used.

If you are using a bridging header, include the CloudantSync.h and you should be good to go:

#import <CDTDatastore/CloudantSync.h>

To add, and read documents in Swift, the basics are:

import CDTDatastore

do {
    let fileManager = FileManager.default

    let documentsDir = fileManager.urls(for: .documentDirectory, in: .userDomainMask).last!

    let storeURL = documentsDir.appendingPathComponent("cloudant-sync-datastore")
    let path = storeURL.path

    let manager = try CDTDatastoreManager(directory: path)
    let datastore = try manager.datastoreNamed("my_datastore")

    // Create a document
    let rev = CDTDocumentRevision(docId: "doc1")
    rev.body = ["description":"Buy Milk",
                "completed": false,
                "type":"com.cloudant.sync.example.task"]

    // Add an attachment - binary data like a JPEG
    let att1 = CDTUnsavedFileAttachment(path: "/path/to/image/jpg",
                                        name: "cute_cat.jpg",
                                        type: "image/jpeg")!
    rev.attachments[att1.name] = att1

    let revision = try datastore.createDocument(from: rev)

    // Read a document
    let docId = revision.docId
    let retrieved = try datastore.getDocumentWithId(docId!)

} catch {
    print("Encountered an error: \(error)")
}

Read more in the CRUD document.

You can subscribe for notifications of changes in the database, which is described in the events documentation. It's still a bit raw right now:

  • You receive a notification for all new revisions in replication (which can be more than one per updated document).

Replicating Data Between Many Devices

Replication is used to synchronise data between the local datastore and a remote database, either a CouchDB instance or a Cloudant database. Many datastores can replicate with the same remote database, meaning that cross-device synchronisation is achieved by setting up replications from each device to the remote database.

Replication is simple to get started in the common cases:

#import <CloudantSync.h>

// Create and start the replicator -- -start is essential!
CDTReplicatorFactory *replicatorFactory =
[[CDTReplicatorFactory alloc] initWithDatastoreManager:manager];

NSString *s = @"https://apikey:[email protected]/my_database";
NSURL *remoteDatabaseURL = [NSURL URLWithString:s];
CDTDatastore *datastore = [manager datastoreNamed:@"my_datastore"];

// Replicate from the local to remote database
CDTPushReplication *pushReplication = [CDTPushReplication replicationWithSource:datastore
                                                                         target:remoteDatabaseURL];
NSError *error;
CDTReplicator *replicator = [replicatorFactory oneWay:pushReplication error:&error];

//check error

// Start the replicator
[replicator start];
import CDTDatastore
do {

    let datastore = try manager.datastoreNamed("my_datastore");

    // Replicate from the local to remote database
    let remote = URL(string: "https://apikey:[email protected]/my_database")!
    datastore.push(to: remote) { error in

        if let error = error {
            print("Encountered an error: \(error)")
        } else {
            print("Replication complete")
        }

    }

} catch {
    print("Encountered an error: \(error)")
}

Read more in the replication docs including how to use IAM authentication instead of username/password.

Finding data

Once you have thousands of documents in a database, it's important to have efficient ways of finding them. We've added an easy-to-use querying API. Once the appropriate indexes are set up, querying is as follows:

NSDictionary *query = @{
    @"name": @"John",         // name equals John
    @"age": @{ @"$gt" : @25}  // age greater than 25
};
CDTQResultSet *result = [datastore find:query];
[result enumerateObjectsUsingBlock:^(CDTDocumentRevision *rev, NSUInteger idx, BOOL *stop) {
    // do something
}];
let query = [
    "name" : "John", // name equals John
    "age" : ["$gt" : 25] // age greater than 25
]
let result = datastore.find(query)
result?.enumerateObjects { rev, idx, stop in
    // do something
}

See Index and Querying Data.

As of version 0.16.0 the indexing and querying code has been re-written and has more features than the previous implementation. For details about migrating to a 0.16.0+ indexing and query version from a previous version see Index and Querying Migration.

Conflicts

An obvious repercussion of being able to replicate documents about the place is that sometimes you might edit them in more than one place at the same time. When the databases containing these concurrent edits replicate, there needs to be some way to bring these divergent documents back together. Cloudant's MVCC data-model is used to do this.

A document is really a tree of the document and its history. This is neat because it allows us to store multiple versions of a document. In the main, there's a single, linear tree -- just a single branch -- running from the creation of the document to the current revision. It's possible, however, to create further branches in the tree. At this point your document is conflicted and needs some surgery to resolve the conflicts and bring it back to full health.

Requirements

All requirements are included in the source code or pulled in as dependencies via pod install.

Contributors

See CONTRIBUTORS.

Contributing to the project

See CONTRIBUTING.

License

See LICENSE

CDTDatastore classes and TouchDB classes

Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.

Used libraries under different licences

  • MYUtilities is licensed under the BSD licence (portions copied into vendor directory).
  • FMDB, by Gus Mueller, is under the MIT License.
  • Google Toolbox For Mac is under the Apache License 2.0.

cdtdatastore's People

Contributors

alfinkel avatar brynh avatar emlaver avatar enquora avatar glynnbird avatar indisoluble avatar jimix avatar leungtkc avatar linjunpop avatar mikerhodes avatar mojito317 avatar p2k avatar rhyshort avatar ricellis avatar sdrew avatar smithsz avatar tomblench avatar tonklon avatar xpqz avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

cdtdatastore's Issues

Set Authorization Header

With reference to this issue here in Android: cloudant/sync-android#36

It would be preferable if this could also be made available in iOS. At the moment, not being able to set authorization headers and having to send username and password via the URL is very insecure.

Implement Continous Replication

The underlying TDReplicator class seems to already support continuous replication. What needs to be done in order to enable continuous replication in CDTReplicator?

Create category on CDTDatastore to manage replications

The aim here is to go from:

CDTReplicatorFactory *replicatorFactory = [[CDTReplicatorFactory alloc] init];
CDTDatastore *datastore = [manager datastoreNamed:@"my_datastore"];
CDTPushReplication *pushReplication = [CDTPushReplication replicationWithSource:datastore target:remoteDatabaseURL];
CDTReplicator *replicator = [replicatorFactory oneWay:pushReplication error:&error];
[replicator start];

to this:

CDTReplicator *replicator = [datastore pushReplicationTarget:remoteDatabaseURL
withDelegate:self
error:&error];
[replicator start];

That is, we manage the replicator factory within the datastore. We shouldn't change the logic other than this.

Avoid calling CDTDocumentRevision initWithDocId: twice in CDTDatastore getDocumentWithId:

After the mutable doc code was landed, [[CDTDocumentRevision alloc] initWithDocId: became a bunch more expensive because we copy the JSON body into a new dictionary -- Adam Cox did some work profiling this, and it was one of our first successes in finding a performance regression from the performance work. We should look to eradicate times where we call it when we don't need to.

For starters, lets see if we can clear the two calls here:

- (CDTDocumentRevision *)getDocumentWithId:(NSString *)docId
                                       rev:(NSString *)revId
                                     error:(NSError *__autoreleasing *)error
{
    if (![self ensureDatabaseOpen]) {
        *error = TDStatusToNSError(kTDStatusException, nil);
        return nil;
    }

    TDStatus status;
    TD_Revision *rev =
        [self.database getDocumentWithID:docId revisionID:revId options:0 status:&status];
    if (TDStatusIsError(status)) {
        if (error) {
            *error = TDStatusToNSError(status, nil);
        }
        return nil;
    }

    CDTDocumentRevision *revision = [[CDTDocumentRevision alloc] initWithDocId:rev.docID
                                                                    revisionId:rev.revID
                                                                          body:rev.body.properties
                                                                       deleted:rev.deleted
                                                                   attachments:@{}
                                                                      sequence:rev.sequence];
    NSArray *attachments = [self attachmentsForRev:revision error:error];

    NSMutableDictionary *attachmentsDict = [NSMutableDictionary dictionary];

    for (CDTAttachment *attachment in attachments) {
        [attachmentsDict setObject:attachment forKey:attachment.name];
    }

    revision = [[CDTDocumentRevision alloc] initWithDocId:rev.docID
                                               revisionId:rev.revID
                                                     body:rev.body.properties
                                                  deleted:rev.deleted
                                              attachments:attachmentsDict
                                                 sequence:rev.sequence];

    return revision;
}

CocoaPods is a requirement to build

Cocoa Pods seems really cool, but what about distributing your code the good ol fashioned way? I can't build this project without Cocoa Pods, which seems like a bad idea since many people may not want this software to dictate whether or not they can use your software.

My suggestions:
List required frameworks/libraries in the documentation.
Include non apple frameworks/libraries in the project.
Build binaries that can be simply dragged and dropped into a project (Couchbase Lite does this).

Sorry for all the whining, but I'm using Couchbase Lite right now and wanted to try out your framework but this CocoaPod thing was an obstacle rather than helpful as you intended.

Improve error when hitting device disk capacity

When the device disk is full the developer will ultimately see a generic "500 Internal DB Error", which is indistinguishable from other errors that can produce the same response. FMDB will print something to the log (NSLog) about it, which seems to be the only way that a developer will know it's a capacity limiting error (assuming that FMDB/sqlite3 reports this error).

Throughout our code we use the FMDatabase -executeUpdate method, which doesn't capture any errors. It only returns a YES/NO. We could migrate to use -executeUpdate:withErrorAndBindings in order to capture FMDB errors and propagate them appropriately.

FMDB/sqlite supports disk full error codes, it is 13 - SQLITE_FULL (http://sqlite.org/rescode.html#full), we should make use of it to provide an improved error.

DB Not opening

I am getting pretty often in iOS app the following message when trying to open the db:
error opening!: 23
Could not create database queue for path /var/mobile/Containers/Data/Application/xxx/dbname.touchdb

Is there any reason why this happens so often? I am using the v0.16 version of CDTDatastore

Query: use enum for `type` in public API

Using an untyped string for type in CDTQIndexManager is confusing and error-prone.

  • Deprecate methods which take an NSString for index
  • Add enum for IndexType with values json and text
  • Replace deprecated methods with new ones taking enum

Query: special characters in index names

In the various [CDTQIndexManager ensureIndexed] variants, the indexName argument is used to dynamically build a table name via string concatenation. This is done because SQL placeholders cannot be used to form table names.

As a consequence, characters which have special meaning to the SQL query parser (such as space or semicolon and a whole host of others) cannot be used for index names, because they cause the SQL parser to throw an error.

Potential fixes:

  • At a minimum this restriction should be documented
  • We should also consider mitigating strategies, like restricting the index name to a "safe" range of characters

any support for replication of named documentation?

according the documentation of cloudant about the named documentation replication :

Example replication of specific documents:

{
"source": "http://username:[email protected]/example-database",
"target": "http://username:[email protected]:5984/example-database",
"doc_ids": ["foo", "bar", "baz"]
}

the CDTDatastore has any function for that?

like
var pullReplication = CDTPullReplication(source: datastore, target: remoteDatabaseURL, ["doc1","doc2"] )

thanks

Geospatial Query Support

Hi,

I've looked in the source but cannot see support yet for geospatial queries. I have an existing project that would be a good fit for CDTDatastore but need to perform a few queries based on the location of a user.

Essentially I need to perform two queries:

  1. Get documents within a rectangle (north, east, south and west)
  2. Get document were the coordinates are closest to the user

I wonder if anyone has any ideas on how I could achieve this with CDTDatastore. One idea I had was to build a separate Sqlite DB with the doc._id and coordinates but I'm not sure if thats my only option.

Many Thanks

Oliver

Update Contributing

After the merge of PR #215 contributing will become out of date. It needs to be updated to provide the correct instructions for setting up a development environment for CDTDatastore.

iOS - Subscribing to Events

I notice that subscribing to events is not currently available in iOS, is this being worked on? Can the branch be made known so that I can contribute?

Storing NSNumber "inifinity" value causes entire body to be dropped

The following unit test fails (add to Tests/Tests/DatastoreCRUD.m to run):

-(void)testNumberInfinity
{
    NSError *error;
    CDTMutableDocumentRevision *doc = [CDTMutableDocumentRevision revision];
    doc.body = [@{
                  @"hello": @"world",
                  @"infinity": @(INFINITY)
                  } mutableCopy];
    CDTDocumentRevision *ob = [self.datastore createDocumentFromRevision:doc error:&error];

    STAssertNil(error, @"Error creating document");
    STAssertNotNil(ob, @"CDTDocumentRevision object was nil");

    CDTDocumentRevision *check = [self.datastore getDocumentWithId:ob.docId error:&error];
    STAssertNil(error, @"Error creating document");
    STAssertNotNil(check, @"CDTDocumentRevision object was nil");
    STAssertTrue([check.docId isEqualToString:ob.docId],
                 @"docId Mismatch: %@ != %@", ob.docId, check.docId);
    STAssertTrue([check.revId isEqualToString:ob.revId],
                 @"revId Mismatch: %@ != %@", ob.revId, check.revId);

    // things start failing here
    STAssertTrue([check.body count] > 0,
                 @"check.body is empty");
    STAssertTrue([ob.body[@"hello"] isEqual:check.body[@"hello"]],
                 @"hello did not match: %@ != %@", ob.body[@"hello"], check.body[@"hello"]);
    STAssertTrue([ob.body[@"infinity"] isEqual:check.body[@"infinity"]],
                 @"infinity did not match: %@ != %@", ob.body[@"infinity"], check.body[@"infinity"]);
}

Also note that ob reports that all is fine.

CDTReplicatior state tests in ReplicationAcceptance.

Add state tests for the following scenarios to ReplicationAcceptance:

  • local database is deleted
  • remote database is deleted
  • loses network connection temporarily
    • for > 60s but < 120s
    • for < 60s
      (the default retry waiting period is 60s)
  • loses network connection permanently
  • remote credentials are changed

Mismatch between documentation and version 1.0.0

The replication documentation references a method startWithTaskGroup. This method does not exist inside 1.0.0. I had to point cocoapods directly at master to use the feature.

I'm guessing someone forgot to release a new pod version when the feature was merged in?

Documentation issue regarding deleted datastores

The documentation for CDTDatastoreManager -deleteDatastoreNamed:error: says

"it is the responsibility of the caller to ensure that extensions should be shutdown (and their underlying databases closed) before calling this method."

However, a CDTDatastore -close does not exist nor is there any documentation on what an extension is and how to shut it down.

Incorrect documentation on CDTDatastore

The documentation on CDTDatastore mentions that conflict resolution is coming, however it has been present for a number of releases, the documentation here needs to be updated to mention the conflicts API.

Confusing Swift Interface

The generated Swift interface for CDTDatatore is confusing and for some features unusable. For example the CDTDocumentRevision class has 4 init methods each with different arguments and nullability. The macros used to manipulate the logging levels are not imported into swift thus Applications written in swift cannot control the logging levels for our classes.

It needs to be investigated how this can be improved, either using new Objc Language features announced at WWDC, or by creating a Swift front end which simplifies the interface. The problem with changing the mapping will result in the breaking changes for the swift interface so this may be in conflict with semver and have to be pushed to a major release rather than a minor.

delete document with old rev that was already deleted returns 404 and not 409

n Cloudant/Couch, when one tries to delete a document for the second time with an old 'rev' value, a 409 error is returned.

14:58:44 > acurl -X POST https://gadamc2.cloudant.com/test -d '{"_id":"tt1", "hellow":"world", "_deleted":true, "_rev":"3-428bcbf5b7ad1cb5f7c9b9e740c0f4ea" }' -H 'Content-Type: application/json'

{"ok":true,"id":"tt1","rev":"4-23650c9a0128ae6820131175b23bad8a"}

15:07:40 > acurl -X POST https://gadamc2.cloudant.com/test -d '{"_id":"tt1", "hellow":"world", "_deleted":true, "_rev":"3-428bcbf5b7ad1cb5f7c9b9e740c0f4ea" }' -H 'Content-Type: application/json' --verbose

  • Adding handle: conn: 0x7fd69a004000
  • Adding handle: send: 0
  • Adding handle: recv: 0
  • Curl_addHandleToPipeline: length: 1
  • - Conn 0 (0x7fd69a004000) send_pipe: 1, recv_pipe: 0
  • About to connect() to gadamc2.cloudant.com port 443 (#0)
  • Trying 184.173.163.133...
  • Connected to gadamc2.cloudant.com (184.173.163.133) port 443 (#0)
  • TLS 1.0 connection using TLS_RSA_WITH_RC4_128_SHA
  • Server certificate: *.cloudant.com
  • Server certificate: DigiCert High Assurance CA-3
  • Server certificate: DigiCert High Assurance EV Root CA

    POST /test HTTP/1.1
    User-Agent: curl/7.30.0
    Host: gadamc2.cloudant.com
    Accept: /
    Content-Type: application/json
    Content-Length: 94

  • upload completely sent off: 94 out of 94 bytes
    < HTTP/1.1 409 Conflict
    < X-Couch-Request-ID: 0ae6cab0
  • Server CouchDB/1.0.2 (Erlang OTP/R14B) is not blacklisted
    < Server: CouchDB/1.0.2 (Erlang OTP/R14B)
    < Date: Sat, 22 Feb 2014 23:08:31 GMT
    < Content-Type: text/plain;charset=utf-8
    < Content-Length: 58
    < Cache-Control: must-revalidate
    <
    {"error":"conflict","reason":"Document update conflict."}
  • Connection #0 to host gadamc2.cloudant.com left intact

However, when performing the same operations in CDTDatastore results in a 404 rather than a 409

Remove Legacy test cases

Legacy Test cases for MYUtilites should be removed, an example of the test cases to be removed can be found here.

Cannot build as a framework

(I am working from one week of total iOS, and XCode experience, so please bear with me!)

I think this project cannot build as a framework when used by a Swift project (at least with XCode 7 beta 6). The main problem is "Include of non-modular header inside framework module".

From my limited research, I gather that this issue is somewhat new (as apparently frameworks are not the only way to organize subprojects); but it is becoming more urgent, since Swift projects cannot work around it. (One can disable this compiler error; however, the disabling is not honored in Swift projects, whether by bug or design.) A clear description of the problem is here: http://inessential.com/2015/03/16/swift_blocker

In any case, it sounds like the situation XCode caught is indeed problematic and should be fixed. (My understanding is that, .h files should not import system-wide .h files--.m files should; something about a naming conflict as multiple frameworks compile together). Here is your dependency, CocoaLumberjack struggling with the same issue.

So, modulo my naïve understanding, to be complete (except of course as a NOFIX), CDTDatastore needs to fix its own issues and then also upgrade to all dependencies when they fix theirs. This issue only applies to this project's specific build failure.

AFAICT, there is only one problem in the codebase:

/Users/jhs/src/cloudant/CDTDatastore/Classes/common/Encryption/Attachments/CDTBlobEncryptedDataConstants.h:20:9: Include of non-modular header inside framework module 'CDTDatastore.CDTBlobEncryptedDataConstants'

No concurrency control for operations in database files: 'open', 'close' & 'delete'

Once we create (and open) a FMDatabase using the methods in TD_Database, all operations in the database are executed in a FMDatabaseQueue, i.e. concurrency is managed through this serial queue. However, when the methods in TD_Database to open, close and delete one of these databases have no concurrency control at all, so it is possible to delete the database from different threads with undefined results.

This bug was first detected and commented #112 (comment) and #112 (comment).

SQLite temporary files are not deleted when the database is deleted

Journal mode for main SQLite database is WAL. In this case, at least one temporary file is created in the same folder adding '-wal' to the name of the database (and also another one adding '-shm'). However the method in TD_Database to delete a database: 'TD_Database:deleteDatabase:' only removes the file for the database.

Can't query embedded document property

I have a document looking like the following: http://pastie.org/private/kmdctsbhgcxx8g9m2msipg
I want to query the documents given a concrete type and uriList.source.

To be able to query this, I create the indexes for those properties as following:

[self.dataStore ensureIndexed:@[@"type"] withName:@"docType"];
[self.dataStore ensureIndexed:@[@"uriList.source", @"uriList.url"] 
                     withName:@"documentUriList"];

So, I create the query:

CDTQResultSet *result = [[self.couchDBProvider getDataStore] 
    find:@{@"type": type, @"uriList.source": source} 
    skip:0 
   limit:0 
  fields:nil 
    sort:nil];

But get no result at all.

Seems that the problem is that uriList is an array of jsons and this is not managed

Expecta uses NS_DESIGNATED_INITIALIZER which is undefined for SDKs before OSX10.10

Using xctool, which just wraps for xcodebuild
When building for OSX10.9:

$ (cd Tests; pod install)
$ xctool -workspace CDTDatastore.xcworkspace -scheme "Tests OSX" -sdk macosx10.9 test
...
In file included from /Users/jimix/work/iOS/CoreData/CDTDatastore/Tests/Pods/Expecta/Expecta/Matchers/EXPMatchers+beCloseTo.m:1:
In file included from /Users/jimix/work/iOS/CoreData/CDTDatastore/Tests/Pods/Expecta/Expecta/Matchers/EXPMatchers+beCloseTo.h:1:
In file included from /Users/jimix/work/iOS/CoreData/CDTDatastore/Tests/Pods/Expecta/Expecta/Expecta.h:10:
In file included from /Users/jimix/work/iOS/CoreData/CDTDatastore/Tests/Pods/Headers/Private/Expecta/ExpectaSupport.h:1:
/Users/jimix/work/iOS/CoreData/CDTDatastore/Tests/Pods/Headers/Private/Expecta/EXPExpect.h:31:159: error: expected ':'
- (instancetype)initWithActualBlock:(id)actualBlock testCase:(id)testCase lineNumber:(int)lineNumber fileName:(const char *)fileName NS_DESIGNATED_INITIALIZER;
                                                                                                                                                              ^
                                                                                                                                                              :
/Users/jimix/work/iOS/CoreData/CDTDatastore/Tests/Pods/Headers/Private/Expecta/EXPExpect.h:43:110: error: expected ':'
- (instancetype)initWithExpectation:(EXPExpect *)expectation selector:(SEL)selector NS_DESIGNATED_INITIALIZER;

I'll follow up on any issues with pre iOS8.

Make Replication a one liner

The aim here is to go from:

CDTReplicator *replicator = [datastore pushReplicationTarget:remoteDatabaseURL 
                                                withDelegate:self
                                                       error:&error];
[replicator start];

to this:

[datastore pushReplicationTarget: remoteDatabaseURL completionBlock: ...];

The work here is therefore to work out how:

  • to call replicator.start from the pushReplicationTarget:completionBlock: method.
  • the arguments to the callback (at least some status and error, like CloudKit).
  • to encapsulate a delegate which calls the callback.

Could not build Objective-C module 'CDTDatastore' - Swift

Hi,
i'm having a problem running my project with CDTDatastore, i'm using Cocoapods and Swift.
When i build the project all goes fine, but when i try to do "import CDTDatastore", Xcode give me a compilation error: "Could not build Objective-C module 'CDTDatastore'", there are others error that are all of the same type, like "Include of non-modular header inside framework module..."
I have some additional information:

  • i use Xcode 7.2
  • in the Podfile i have "use_frameworks!"
  • if i remove "use_frameworks!" and i import "CloudantSync.h" in the bridging header all goes fine, but i can't remove "use_frameworks!"

ATS Enforcement EOY 2016

Apple announced at WWDC that ATS will be strictly enforced from the end of the year. We should make sure we don't need a ATS exception, and we make it easier for users to replicate using https with cloudant.

Query: Implement `ensureIndexed:(NSArray *)fieldNames`

Most users don't care about index names and it should be straightforward enough to generate unique ones on the fly.

This is also relevant because it's easy enough for users to specify index names which will cause an error.

Remove Exposure of TDStatus Errors

Exposure of TDStatus errors should be eliminated to do this the following steps should be followed:

  1. Use a single error domain across the CDT parts of the library -- CDTDatastoreErrorDomain.
  2. Devote a block of 1000 error codes to each subsystem
    (replication, attachments, CRUD, indexing).

This allows the developer to see, for example, 1007 and know it's a CRUD
error, and we can expand the error codes produced by a subsystem (up to
999 codes, anyway).

  1. Audit each error site, and decide what the most useful error is, and
    whether it needs a unique code.
  2. Wrap TD Errors.
  3. Document all our error codes properly. Using a single domain and
    declaring them a single header.

TDPusher only writes checkpoint document at completion, rather than as batches are written

The last sequence value isn't written to the remote checkpoint doc from time-to-time by the push replicator. It only writes the lastSequence value at the end of replication, when TDReplicator -stopped is called. This is okay as long as the replicator exits gracefully. However, if the code crashes completely, then all push replication progress will be lost.

The push replicator only calls TDReplicator -saveLastSequence once, at the end. It doesn’t even try during replications. whereas, the pull replicator does make attempts at times during replication.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.