Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

createDatabaseIfNotExists throws "org.ektorp.DbAccessException: A database with path X already exists" #159

Closed
huxi opened this issue Feb 4, 2014 · 5 comments

Comments

@huxi
Copy link
Contributor

huxi commented Feb 4, 2014

This happens pretty random and I suspect that the database is under load...

Exception in thread "main" org.ektorp.DbAccessException: A database with path /string_list_nl/ already exists
        at org.ektorp.impl.StdCouchDbInstance.createDatabase(StdCouchDbInstance.java:51)
        at org.ektorp.impl.StdCouchDbInstance.createDatabase(StdCouchDbInstance.java:46)
        at org.ektorp.impl.StdCouchDbConnector.createDatabaseIfNotExists(StdCouchDbConnector.java:406)
        at org.ektorp.support.CouchDbRepositorySupport.<init>(CouchDbRepositorySupport.java:53)
        at org.ektorp.support.CouchDbRepositorySupport.<init>(CouchDbRepositorySupport.java:44)

Using ektorp 1.4.1 with couchdb 1.5.0.

Code looks like this:

@Views({
    @View(name = "all", file="/couch/list/allView.json"),
    @View(name = "tag_counts", file="/couch/list/listEntryCounts.json")
})
public class StringListCouchDbRepository
        extends CouchDbRepositorySupport<StringList> {

    public StringListCouchDbRepository(CouchDbConnector db) {
        super(StringList.class, db);
        initStandardDesignDocument();
    }
    // [..]
}
@huxi
Copy link
Contributor Author

huxi commented Feb 4, 2014

Additional info about dependencies:

[INFO] +- org.ektorp:org.ektorp.spring:jar:1.4.1:runtime
[INFO] |  \- org.aspectj:aspectjweaver:jar:1.7.4:runtime (version managed from 1.6.9)
[INFO] |  +- org.ektorp:org.ektorp:jar:1.4.1:compile
[INFO] |  |  +- org.apache.httpcomponents:httpclient:jar:4.3.2:compile (version managed from 4.2.5)
[INFO] |  |  |  +- org.apache.httpcomponents:httpcore:jar:4.3.1:compile
[INFO] |  |  |  \- commons-codec:commons-codec:jar:1.7:compile (version managed from 1.6)
[INFO] |  |  +- org.apache.httpcomponents:httpclient-cache:jar:4.3.2:compile (version managed from 4.2.5)
[INFO] |  |  +- commons-io:commons-io:jar:2.4:compile (version managed from 2.0.1)
[INFO] |  |  \- com.fasterxml.jackson.core:jackson-annotations:jar:2.3.1:compile (version managed from 2.2.2)

@helun
Copy link
Owner

helun commented Feb 6, 2014

Do you create databases on the fly?
It looks like there might be multiple nodes in your system that is trying to create the same db at the same time.

@huxi
Copy link
Contributor Author

huxi commented Feb 6, 2014

The databases are all existing already and the exception is happening really randomly. I'm executing similar actions on a bunch of databases of this type where only the dbName is changed. But those are all fresh instances that are sharing the same CouchDbInstance. Executing those actions multiple times results in the exception above with different dbNames. Databases that worked on a previous run would suddenly throw the exception and vice versa.

The code initializing our repository looks like this:

    private void setCouchDbInstance(CouchDbInstance couchDbInstance)
    {
        this.couchDbInstance = couchDbInstance;
        StdCouchDbConnector db = new StdCouchDbConnector(dbName, couchDbInstance, new ResourceObjectMapperFactory());
        repo=new StringListCouchDbRepository(db);
    }

    private static class ResourceObjectMapperFactory
        implements ObjectMapperFactory
    {
        public ObjectMapper createObjectMapper()
        {
            ObjectMapper result = new ObjectMapper();
            result.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false);
            result.setDateFormat(new ISO8601DateFormat());
            result.registerModule(new StringListModule());
            result.registerModule(new AfterburnerModule());
            return result;
        }

        public ObjectMapper createObjectMapper(CouchDbConnector connector)
        {
            return createObjectMapper();
        }
    }

And the configuration of the CouchDbInstance looks like this:

<bean name="couchDb" class="org.ektorp.impl.StdCouchDbInstance">
    <constructor-arg>
        <bean class="org.ektorp.spring.HttpClientFactoryBean" p:username="xxx" p:password="yyy" p:port="5984">
            <property name="host" value="zzz"/>
            <property name="autoUpdateViewOnChange" value="true"/>
        </bean>
    </constructor-arg>
</bean>

I suspect that our CouchDB was barfing under heavy load and returned some error (probably 500) which is interpreted as "does not exist" in StdCouchDbInstance

    public boolean checkIfDbExists(DbPath db) {
        return restTemplate.head(db.getPath(), new StdResponseHandler<Boolean>() {
        @Override
        public Boolean error(HttpResponse hr) {
            return false;
        }
        @Override
        public Boolean success(HttpResponse hr) throws Exception {
            return true;
        }
        });
    }

I'd suggest throwing a DbAccessException if hr.getCode() returns an unexpected value in error(...) instead of just returning false in any error case. That exception should include the message from the server. I highly suspect that an error should be thrown in my case (because the CouchDB was acting funky, returning 500 in case of some other calls) but the message that is currently produced is wrong and misleading.

@huxi
Copy link
Contributor Author

huxi commented Feb 24, 2014

I can confirm that the couchdb is returning 500 in those cases (for unrelated reasons). This causes checkIfDbExists(..) to erroneously return false.

@huxi
Copy link
Contributor Author

huxi commented May 18, 2014

I've sent #186 to fix this. The tests are working (after fixing mock assumptions according to the new implementation) but I didn't check it against a real CouchDB since I don't know if/how I could do that in your build.

Let me know if anything is wrong.

@helun helun closed this as completed in 60b6946 Aug 19, 2014
helun pushed a commit that referenced this issue Aug 19, 2014
Fixes #159 and some race conditions.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants