Hi All,

We just had the discussion regarding throwing exceptions in the Cassandra 
Persistence Manager API. In line with this discussion we also need to look at 
our CRUD APIs. A simple example is a CRUD interface on oAuth service consumers. 
Currently, this API consists of 4 methods:

OAuthServiceConsumer get(String consumerKey);
void add(OAuthServiceConsumer consumer);
void remove(OAuthServiceConsumer consumer);
void update(OAuthServiceConsumer consumer);

Now one important problem with this API definition is that it is kind of 
'impossible' to implement properly in Cassandra. Cassandra does not 
differentiate between add and update. It only supports a setValue method, which 
creates the value if it didn't exist yet and updates the existing value if it 
did. An add method that only adds the consumer if it doesn't exist yet cannot 
be implemented, as Cassandra does not support locking (out of the box). Of 
course, you could still use the if (!exists(A)) add(A) approach and this will, 
in many cases, do the job. However, there is no guarantee; another consumer 
with the same key could have been added in the meantime and this construction 
would just overwrite it, which is not what the API promised to do.
So since the CRUD API for consumers is supposed to be a generic API, suited to 
be implemented by several storages, I don't think this API definition is proper 
for the Cassandra case. add and update should be merged into a single method 
and if a developer wants to do stuff like if(exists(A)) add(A), he still can.
Another issue is that in Cassandra you cannot tell when a remove() did actually 
remove a row, or that it didn't have any effect since the row to be removed 
didn't exist. Hence, the removeConsumer method should not differentiate between 
these two cases. Still the invoker can use if (exists(A)) constructions if he 
really needs it, but the API should not define behavior that cannot be possibly 
implemented by certain storage implementations.

Now this is all true from a Cassandra perspective. But if I would create a 
relational database implementation, I would have a different opinion. One of 
the reasons to choose for a relational database would be its strong consistent 
behavior, transactions support and locking support. But with the API above I 
cannot expose all this strength. In the implementation of add(consumer) I could 
have set a lock on the table and ensure that it doesn't exist yet, before 
creating it. This makes sense, as it is possible that two different users are 
trying to add different consumers simultaneously, but coincidently with the 
same key. I could use locking to let the first add succeed and notify the 
second user that a consumer with this key already exists, where in Cassandra 
the first user would just have 'bad luck'. So I would feel that this API 
definition is too limited and would suggest separate add and update methods.

Maybe this proves once again that our conclusion as mentioned on 
http://www.amdatu.org/confluence/display/Amdatu/Persistence was correct; there 
is no such thing as a generic persistence API, suitable for all storages. 
Still, this is what we are trying to do with our 'StorageProvider' interfaces.

So again, what do you think?

Regards, Ivo

GX Software | Ivo Ladage-van Doorn | Product Architect | Wijchenseweg 111 | 
6538 SW Nijmegen | The Netherlands | T +31(0)24 - 388 82 61 | F +31(0)24 - 388 
86 21 | 
[email protected]<mailto:[email protected]> | 
www.gxsoftware.com<http://www.gxsoftware.com> | 
twitter.com/GXSoftware<http://twitter.com/GXSoftware>

_______________________________________________
Amdatu-developers mailing list
[email protected]
http://lists.amdatu.org/mailman/listinfo/amdatu-developers

Reply via email to