When I try to lock a line in my table, sometimes null is returned. What does that mean? I verify that the domain instance was not null before the lock:
println state
state = State.lock(state.id)
println state
This outputs:
State 1
null
("State 1" is the String representation of state)
By doing this you're switching from GORM optimistic locking (which compares version of your object before your update ) by a pessimitic lock which implies that read operations will be blocking until the lock is released. Use the closure below if you want to retrieve a value (see method returnValue):
State.withPessimisticLock(state.id) { Object lockedDomain ->
return "OK"
}.onNotFound { ->
return "NG"
}
assert result.returnValue == "OK"
By the way, a transaction is required, so the null which is returned in your question probably means your object is out of the transaction.
Related
I'd like to enforce that a value is set rather than using the default "" if one of the other values is a certain string.
For example I have:
module "test_beanstalk" {
tier = "Worker"
queue = "myQueue"
///
}
in this, when tier is set to worker I'd like to enforce that queue is also set. In the above example there's a scenario where the queue can be omitted resulting in aws spawning a generic one rather than using the queue that is required for that particular application.
Such feature is not directly supported in TF. But you can force TF to error out using locals and some condition that will simply lead to error if your verification fails. For example, in your test_beanstalk you can have:
variable "tier" {
default = "Worker"
}
variable "queue" {
default = ""
}
locals {
if_queue_given = var.tier == "Worker" && var.queue == "" ? tonumber("queue can't be empty") : 1
}
The tonumber("queue can't be empty") will be executed and will lead to TF error, if the condition var.tier == "Worker" && var.queue == "" is true.
I use akka's PersistentActor with sharding in a cluster to keep track of my state. I have a 'Room' which i can update via following code:
case UpdateRoom(id, room, userId) => ((ret: ActorRef) => {
(userRegion ? GetRoleForRoom(userId, id)).mapTo[String] map { role =>
if (role == "owner") {
state = Some(room)
ret ! Success(room)
eventRegion ! RoomEventPackage(id, RoomUpdated(room))
println("works")
persist(RoomUpdated(room))(e => println("this doesn't always fire")
} else {
ret ! Failure(InsufficientRights(role, "Update Room"))
}
}
Problem is that persist only works every other time while the rest of the function works as expected. ("works" gets printed every time, "this doesn't always fire" every other but then two times).
I always have to fire the update command two times to store my Event, but then it appears to be stored for both times i fired the command.
Am i missing an important part of akka persist?
I think that you are making a grave mistake in the world of Actor: accessing the actor (mutable) state from outside. In your case, this happens twice from within the callback of the Future returned by ask/?:
when updating state: state = Some(room)
when calling persist
The only safe way to deal with asking from within your Actor and subsequently modifying the actor's state, is to send a message to the same actor from ask's callback, to that end, you can use pipeTo.
Using a simplified version of your code to illustrate:
case UpdateRoom(id, room, userId) =>
val answer = (userRegion ? GetRoleForRoom(userId, id)).mapTo[String] map(role => RoleForRoom(id, room, userId, role))
answer piepTo self
case RoleForRoom(id, room, userId, room) =>
if (role == "owner") {
state = Some(room)
eventRegion ! RoomEventPackage(id, RoomUpdated(room))
persist(RoomUpdated(room))(e => println("this is safe"))
}
see also: https://doc.akka.io/docs/akka/2.5.6/scala/general/jmm.html#actors-and-shared-mutable-state
Since upgrading my Neo4j from 1.9.8 to 2.1.2. and Spring-Data from 3.2.0 to 3.2.5, I'm seeing a "RollbackException" when I attempt to call TopLevelTransaction.close(..) from within a Transaction. This does not occur if the thread doesn't already have a Transaction associated with it.
neo4j.kernel.TopLevelTransaction.close(TopLevelTransaction.java:134)
~[neo4j-kernel-2.1.2.jar:2.1.2]
at org.neo4j.kernel.TopLevelTransaction.finish(TopLevelTransaction.java:111)
.... Caused by: javax.transaction.RollbackException: Failed to commit, transaction rolled back
at org.neo4j.kernel.impl.transaction.TxManager.rollbackCommit(TxManager.java:629)
at org.neo4j.kernel.impl.transaction.TxManager.commit(TxManager.java:390)
at org.neo4j.kernel.impl.transaction.TransactionImpl.commit(TransactionImpl.java:123)
at org.neo4j.kernel.TopLevelTransaction.close(TopLevelTransaction.java:124)
Before the exception is thrown, the transaction was marked as "rollback only". This occurred when I called CreateObjectiveTxTask.createObjectiveRuleRelationships(..), which results in a call to TypeRepresentationStrategyFactory.chooseStrategy(..).
private static Strategy chooseStrategy(GraphDatabase graphDatabaseService) {
try (Transaction tx = graphDatabaseService.beginTx()) {
if (AbstractIndexBasedTypeRepresentationStrategy.isStrategyAlreadyInUse(graphDatabaseService)) return Strategy.Indexed;
if (SubReferenceNodeTypeRepresentationStrategy.isStrategyAlreadyInUse(graphDatabaseService)) return Strategy.SubRef;
if (LabelBasedNodeTypeRepresentationStrategy.isStrategyAlreadyInUse(graphDatabaseService)) return Strategy.Labeled;
tx.success();
return Strategy.Labeled;
}
}
This method created a PlaceboTransaction, detected that the GraphDatabase instance is already using Index strategy, so closed the transaction without trying to call "success()" on it.
Is this likely to have caused the RollbackException?
What might cause SDN to close PlaceboTransaction before calling "success()" on it, and how can I stop SDN from doing this?
Perhaps there is a bug in TyperRepresentationStrategyFactory.chooseStrategy(..)
The most recent Git commit (b40ea309) for this code moved the tx.success() to where it only effects a Transaction if a strategy is not already in use.
private static Strategy chooseStrategy(GraphDatabase graphDatabaseService) {
Transaction tx = graphDatabaseService.beginTx();
try {
if (isAlreadyIndexed(graphDatabaseService)) return Strategy.Indexed;
if (isAlreadySubRef(graphDatabaseService)) return Strategy.SubRef;
if (isAlreadyLabeled(graphDatabaseService)) return Strategy.Labeled;
} finally {
tx.success();tx.finish();
}
Became
try (Transaction tx = graphDatabaseService.beginTx()) {
if (AbstractIndexBasedTypeRepresentationStrategy.isStrategyAlreadyInUse(graphDatabaseService)) return Strategy.Indexed;
if (SubReferenceNodeTypeRepresentationStrategy.isStrategyAlreadyInUse(graphDatabaseService)) return Strategy.SubRef;
if (LabelBasedNodeTypeRepresentationStrategy.isStrategyAlreadyInUse(graphDatabaseService)) return Strategy.Labeled;
tx.success();
return Strategy.Indexed;
}
When I revert this change, I no longer see the RollbackException.
I'm experiencing some troubles with my program.
I have a process that calls a function (Take_Job) that is supposed to remain blocked until a time (MINIMUM_WAIT) passes. If it doesn't happen that way, a message informing of this situation will appear.
for Printer_Id in Type_Printer_Id loop
select
delay MINIMUM_WAIT
Pragma_Assert (True, "");
then abort
Take_Job (Controller,
Printer_Id,
Max_Tonner,
Job,
Change_Tonner);
Pragma_Assert
(False,
"Testing of Take_Job hasn't been successful. It should have remained blocked.");
end select;
end loop;
The function Take_Job calls to an entry in a protected object:
procedure Take_Job (R : in out Controller_Type;
Printer : in Type_Printer_Id;
Siz : in Typo_Volume;
Job : out Typo_Job;
Excep_Tonner : out Boolean) is
begin
R.Take_Job(Printer, Siz, Job, Excep_Tonner);
end Take_Job;
Where "R" is the protected object.
The following code is the entry of the protected object. Actually, the "when" condition is True because I need to check some stuff with the parameters of the entry. Since Ada doesn't allow me to do that, I copy the parameters inside the protected object and call to a "delayed entry", then in the "delayed entry" I will make sure that the condition is met before proceeding.
entry Take_Job(Printer_Id: in Type_Printer_Id; Remaining: in Type_Volume; Job: out Type_Job; exceptionTonner: out Boolean)
when True is
begin
Copy_Remaining(Printer_Id) := Remaining;
requeue Take_Job_Delayed(Printer_Id);
end Take_Job;
Let's see the "delayed entry" code:
entry Take_Job_Delayed(for J in Type_Printer_Id)(Printer_Id: in Type_Printer_Id; Remaining: in Type_Volume; Job: out Type_Job; exceptionTonner: out Boolean)
when False is -- I've done this on purpose
begin
null; -- Actually, there would be a lot of code here
end Take_Job_Delayed;
Let's say that my goal is to pass the MINIMUM_WAIT and run the "Pragma_Assert(True, "")". If I put the "when" condition of Take_Job to "False", then everything works fine. Take_Job is never accepted and the Pragma_Assert will be executed. If I set it to "True" and the "when" condition of Take_Job_Delayed to "False", I don't get the same effect and the process gets blocked and neither of the Pragma_Asserts will be executed.
Why? It looks like the problem is in the "requeue" or somewhere near that, but why is this happening?
You need to do the requeue with abort;
entry Take_Job(Printer_Id: in Type_Printer_Id;
Remaining: in Type_Volume;
Job: out Type_Job;
exceptionTonner: out Boolean)
when True is
begin
Copy_Remaining(Printer_Id) := Remaining;
requeue Take_Job_Delayed(Printer_Id) with abort;
end Take_Job;
because otherwise the opportunity to abort the entry call has been lost. There are details in ARM 9.5.4, and a more understandable explanation in Burns & Wellings, “Concurrency in Ada”.
I am using JPA 3, with annotation (no mapping file) and with provider org.hibernate.ejb.HibernatePersistence
I need to have optimistic concurrency.
1)I tried to rely on the tag called , it did not work.
2)
So I decided to do it with java code. I have a mergeServiceRequest method and an object with type Request as follows: I start a transaction, lock the request object,
then try to get a Request object newRequest from database, compare its timestamp with the current one request. If they do not match, I throw an exception; if they match, then I update the current request enter code herewith current time and save it to database.
I need to lock the object manually, because by starting a transaction from session, it does not put a lock on the row in database. I wrote some java code which shows that a transaction does not lock the record in database automatically.
Problem with this approach is the query
Request newRequest=entityManager.createQuery("select r from Request r where serviceRequestId = " + request.getServiceRequestId());
always return same object as request. "request" is in the session entityManger, and the query always return what is cached in the session. I tried all the five query.setHint lines and I still get same result: no database query is performed, the result is from session cache directly.
#Transactional
public void mergeServiceRequest(Request request) {
System.out.println("ServiceRequestDao.java line 209");
EntityTransaction transaction = entityManager.getTransaction();
transaction.begin();
entityManager.lock(request, LockModeType.WRITE); // use to lock the database row
Query query = entityManager.createQuery("select r from Request r where serviceRequestId = " + request.getServiceRequestId());
//query.setHint("javax.persistence.cache.retrieveMode", "BYPASS");
//query.setHint("org.hibernate.cacheMode", CacheMode.REFRESH);
//query.setHint("javax.persistence.cache.retrieveMode", CacheMode.REFRESH);
//query.setHint("javax.persistence.retrieveMode", CacheMode.REFRESH);
//query.setHint(QueryHints.CACHE_USAGE, CacheUsage.DoNotCheckCache);
Request newRequest=(Request)query.getSingleResult();
if (! newRequest.getLastUpdatedOn().equals(request.getLastUpdatedOn())) {
throw new StaleObjectStateException(request.getClass().toString(), request.getServiceRequestId());
}
request.setLastUpdatedOn(new Date(System.currentTimeMillis()));
entityManager.persist(request);
entityManager.flush();
transaction.commit();
}
3)So I also tried to use another session get query the newRequest, if I do that, the newRequest will be different from request. But for some reason, if I do that, then the lock on request object is never released, even after the transaction commit. Code looks like below
#Transactional
public void mergeServiceRequest(Request request) {
System.out.println("ServiceRequestDao.java line 209");
EntityTransaction transaction = entityManager.getTransaction();
transaction.begin();
entityManager.lock(request, LockModeType.WRITE); // use to lock the database row
Request newRequest=findRequest(request.getServiceRequestId()); // get it from another session
if (! newRequest.getLastUpdatedOn().equals(request.getLastUpdatedOn())) {
throw new StaleObjectStateException(request.getClass().toString(), request.getServiceRequestId());
}
request.setLastUpdatedOn(new Date(System.currentTimeMillis()));
entityManager.persist(request);
entityManager.flush();
transaction.commit();
//lock on the database record is not released after this, and even after entityManager is closed
}
Could anyone help me on this?
Thanks.
Daniel