Skip to content

Commit 356c318

Browse files
authored
[#12048] Fix account request indexing (#12967)
* Add isTransactionNeeded method to Action * Remove delay from taskqueuer * Change CreateAccountRequest to handle own transactions
1 parent c4fe140 commit 356c318

File tree

8 files changed

+97
-13
lines changed

8 files changed

+97
-13
lines changed

src/it/java/teammates/it/ui/webapi/CreateAccountRequestActionIT.java

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,12 @@
11
package teammates.it.ui.webapi;
22

3+
import org.testng.annotations.BeforeMethod;
34
import org.testng.annotations.Test;
45

56
import teammates.common.util.Const;
67
import teammates.common.util.EmailType;
78
import teammates.common.util.EmailWrapper;
9+
import teammates.common.util.HibernateUtil;
810
import teammates.storage.sqlentity.AccountRequest;
911
import teammates.ui.output.JoinLinkData;
1012
import teammates.ui.request.AccountCreateRequest;
@@ -26,6 +28,13 @@ String getRequestMethod() {
2628
return POST;
2729
}
2830

31+
@BeforeMethod
32+
@Override
33+
protected void setUp() {
34+
// CreateAccountRequestAction handles its own transactions;
35+
// There is thus no need to setup a transaction.
36+
}
37+
2938
@Override
3039
@Test
3140
protected void testExecute() throws Exception {
@@ -37,7 +46,9 @@ protected void testExecute() throws Exception {
3746
CreateAccountRequestAction action = getAction(request);
3847
JsonResult result = getJsonResult(action);
3948
JoinLinkData output = (JoinLinkData) result.getOutput();
49+
HibernateUtil.beginTransaction();
4050
AccountRequest accountRequest = logic.getAccountRequest("[email protected]", "The Fellowship of the Ring");
51+
HibernateUtil.commitTransaction();
4152
assertEquals("[email protected]", accountRequest.getEmail());
4253
assertEquals("Frodo Baggins", accountRequest.getName());
4354
assertEquals("The Fellowship of the Ring", accountRequest.getInstitute());

src/main/java/teammates/logic/api/TaskQueuer.java

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -228,10 +228,8 @@ public void scheduleAccountRequestForSearchIndexing(String email, String institu
228228
paramMap.put(ParamsNames.INSTRUCTOR_EMAIL, email);
229229
paramMap.put(ParamsNames.INSTRUCTOR_INSTITUTION, institute);
230230

231-
// TODO: change the action CreateAccountRequestAction to call scheduleAccountRequestForSearchIndexing
232-
// after AccountRequest is inserted in the DB
233-
addDeferredTask(TaskQueue.SEARCH_INDEXING_QUEUE_NAME, TaskQueue.ACCOUNT_REQUEST_SEARCH_INDEXING_WORKER_URL,
234-
paramMap, null, 60);
231+
addTask(TaskQueue.SEARCH_INDEXING_QUEUE_NAME, TaskQueue.ACCOUNT_REQUEST_SEARCH_INDEXING_WORKER_URL,
232+
paramMap, null);
235233
}
236234

237235
/**

src/main/java/teammates/logic/api/UserProvision.java

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
import teammates.common.datatransfer.UserInfo;
44
import teammates.common.datatransfer.UserInfoCookie;
55
import teammates.common.util.Config;
6+
import teammates.common.util.HibernateUtil;
67
import teammates.logic.core.InstructorsLogic;
78
import teammates.logic.core.StudentsLogic;
89
import teammates.sqllogic.core.UsersLogic;
@@ -48,6 +49,16 @@ public UserInfo getCurrentUser(UserInfoCookie uic) {
4849
return user;
4950
}
5051

52+
/**
53+
* Gets the information of the current logged in user, with an SQL transaction.
54+
*/
55+
public UserInfo getCurrentUserWithTransaction(UserInfoCookie uic) {
56+
HibernateUtil.beginTransaction();
57+
UserInfo userInfo = getCurrentUser(uic);
58+
HibernateUtil.commitTransaction();
59+
return userInfo;
60+
}
61+
5162
// TODO: method visibility to package-private after migration
5263
/**
5364
* Gets the current logged in user.

src/main/java/teammates/sqllogic/api/Logic.java

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,19 @@ public AccountRequest createAccountRequest(String name, String email, String ins
9494
return accountRequestLogic.createAccountRequest(name, email, institute);
9595
}
9696

97+
/**
98+
* Creates a or gets an account request.
99+
*
100+
* @return newly created account request.
101+
* @throws InvalidParametersException if the account request details are invalid.
102+
* @throws EntityAlreadyExistsException if the account request already exists.
103+
*/
104+
public AccountRequest createAccountRequestWithTransaction(String name, String email, String institute)
105+
throws InvalidParametersException {
106+
107+
return accountRequestLogic.createOrGetAccountRequestWithTransaction(name, email, institute);
108+
}
109+
97110
/**
98111
* Gets the account request with the given email and institute.
99112
*

src/main/java/teammates/sqllogic/core/AccountRequestsLogic.java

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
import teammates.common.exception.EntityDoesNotExistException;
77
import teammates.common.exception.InvalidParametersException;
88
import teammates.common.exception.SearchServiceException;
9+
import teammates.common.util.HibernateUtil;
910
import teammates.storage.sqlapi.AccountRequestsDb;
1011
import teammates.storage.sqlentity.AccountRequest;
1112
import teammates.storage.sqlsearch.AccountRequestSearchManager;
@@ -126,4 +127,26 @@ public List<AccountRequest> searchAccountRequestsInWholeSystem(String queryStrin
126127
throws SearchServiceException {
127128
return accountRequestDb.searchAccountRequestsInWholeSystem(queryString);
128129
}
130+
131+
/**
132+
* Creates an or gets an account request.
133+
*/
134+
public AccountRequest createOrGetAccountRequestWithTransaction(String name, String email, String institute)
135+
throws InvalidParametersException {
136+
AccountRequest toCreate = new AccountRequest(email, name, institute);
137+
HibernateUtil.beginTransaction();
138+
AccountRequest accountRequest;
139+
try {
140+
accountRequest = accountRequestDb.createAccountRequest(toCreate);
141+
HibernateUtil.commitTransaction();
142+
} catch (InvalidParametersException ipe) {
143+
HibernateUtil.rollbackTransaction();
144+
throw new InvalidParametersException(ipe);
145+
} catch (EntityAlreadyExistsException eaee) {
146+
// Use existing account request
147+
accountRequest = getAccountRequest(email, institute);
148+
HibernateUtil.commitTransaction();
149+
}
150+
return accountRequest;
151+
}
129152
}

src/main/java/teammates/ui/servlets/WebApiServlet.java

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,14 @@ private void invokeServlet(HttpServletRequest req, HttpServletResponse resp) thr
6060

6161
try {
6262
action = ActionFactory.getAction(req, req.getMethod());
63-
ActionResult result = executeWithTransaction(action, req);
63+
ActionResult result;
64+
65+
if (action.isTransactionNeeded()) {
66+
result = executeWithTransaction(action, req);
67+
} else {
68+
result = executeWithoutTransaction(action, req);
69+
}
70+
6471
statusCode = result.getStatusCode();
6572
result.send(resp);
6673
} catch (ActionMappingException e) {
@@ -127,6 +134,14 @@ private ActionResult executeWithTransaction(Action action, HttpServletRequest re
127134
}
128135
}
129136

137+
private ActionResult executeWithoutTransaction(Action action, HttpServletRequest req)
138+
throws InvalidOperationException, InvalidHttpRequestBodyException, UnauthorizedAccessException {
139+
action.init(req);
140+
action.checkAccessControl();
141+
142+
return action.execute();
143+
}
144+
130145
private void throwErrorBasedOnRequester(HttpServletRequest req, HttpServletResponse resp, Exception e, int statusCode)
131146
throws IOException {
132147
// The header X-AppEngine-QueueName cannot be spoofed as GAE will strip any user-sent X-AppEngine-QueueName headers.

src/main/java/teammates/ui/webapi/Action.java

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -216,7 +216,11 @@ private void initAuthInfo() {
216216
} else {
217217
String cookie = HttpRequestHelper.getCookieValueFromRequest(req, Const.SecurityConfig.AUTH_COOKIE_NAME);
218218
UserInfoCookie uic = UserInfoCookie.fromCookie(cookie);
219-
userInfo = userProvision.getCurrentUser(uic);
219+
if (isTransactionNeeded()) {
220+
userInfo = userProvision.getCurrentUser(uic);
221+
} else {
222+
userInfo = userProvision.getCurrentUserWithTransaction(uic);
223+
}
220224
}
221225

222226
authType = userInfo == null ? AuthType.PUBLIC : AuthType.LOGGED_IN;
@@ -480,6 +484,14 @@ InstructorPermissionSet constructInstructorPrivileges(Instructor instructor, Str
480484
return privilege;
481485
}
482486

487+
/**
488+
* Checks if the action requires a SQL transaction when executed.
489+
* If false, the action will have to handle its own SQL transactions.
490+
*/
491+
public boolean isTransactionNeeded() {
492+
return true;
493+
}
494+
483495
/**
484496
* Gets the minimum access control level required to access the resource.
485497
*/

src/main/java/teammates/ui/webapi/CreateAccountRequestAction.java

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
package teammates.ui.webapi;
22

3-
import teammates.common.exception.EntityAlreadyExistsException;
43
import teammates.common.exception.InvalidParametersException;
54
import teammates.common.util.EmailWrapper;
65
import teammates.storage.sqlentity.AccountRequest;
@@ -13,6 +12,11 @@
1312
*/
1413
public class CreateAccountRequestAction extends AdminOnlyAction {
1514

15+
@Override
16+
public boolean isTransactionNeeded() {
17+
return false;
18+
}
19+
1620
@Override
1721
public JsonResult execute()
1822
throws InvalidHttpRequestBodyException, InvalidOperationException {
@@ -25,16 +29,13 @@ public JsonResult execute()
2529
AccountRequest accountRequest;
2630

2731
try {
28-
accountRequest = sqlLogic.createAccountRequest(instructorName, instructorEmail, instructorInstitution);
29-
taskQueuer.scheduleAccountRequestForSearchIndexing(instructorEmail, instructorInstitution);
32+
accountRequest =
33+
sqlLogic.createAccountRequestWithTransaction(instructorName, instructorEmail, instructorInstitution);
3034
} catch (InvalidParametersException ipe) {
3135
throw new InvalidHttpRequestBodyException(ipe);
32-
} catch (EntityAlreadyExistsException eaee) {
33-
// Use existing account request
34-
accountRequest = sqlLogic.getAccountRequest(instructorEmail, instructorInstitution);
3536
}
3637

37-
assert accountRequest != null;
38+
taskQueuer.scheduleAccountRequestForSearchIndexing(instructorEmail, instructorInstitution);
3839

3940
if (accountRequest.getRegisteredAt() != null) {
4041
throw new InvalidOperationException("Cannot create account request as instructor has already registered.");

0 commit comments

Comments
 (0)