Skip to content
Snippets Groups Projects
Commit 902c1723 authored by Paul-Christian Volkmer's avatar Paul-Christian Volkmer
Browse files

Store feedback in memory using FeedbackStorage

With this patch all feedbacks will be stored in memory without any
interaction with CouchDB. Due to in memory storage, all feedbacks will
be removed if server gets restartet.

Depending on new requests, feedbacks will be deleted after some time. 
parent 1b79491b
No related merge requests found
package de.thm.arsnova;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import de.thm.arsnova.dao.IDatabaseDao;
import de.thm.arsnova.entities.Feedback;
import de.thm.arsnova.entities.User;
import de.thm.arsnova.exceptions.NotFoundException;
public class FeedbackStorage {
private static class FeedbackStorageObject {
private int value;
private Date timestamp;
private User user;
public FeedbackStorageObject(int initValue, User u) {
this.value = initValue;
this.timestamp = new Date();
this.user = u;
}
public int getValue() {
return value;
}
public Date getTimestamp() {
return timestamp;
}
public boolean fromUser(User u) {
return u.getUsername().equals(user.getUsername());
}
}
private Map<String, Map<String, FeedbackStorageObject>> data;
private IDatabaseDao dao;
public FeedbackStorage(IDatabaseDao newDao) {
this.data = new HashMap<String, Map<String,FeedbackStorageObject>>();
this.dao = newDao;
}
public Feedback getFeedback(String keyword) {
int a = 0;
int b = 0;
int c = 0;
int d = 0;
if (dao.getSession(keyword) == null) {
throw new NotFoundException();
}
if (data.get(keyword) == null) {
return new Feedback(0, 0, 0, 0);
}
for (FeedbackStorageObject fso : data.get(keyword).values()) {
switch (fso.getValue()) {
case Feedback.FEEDBACK_FASTER:
a++;
break;
case Feedback.FEEDBACK_OK:
b++;
break;
case Feedback.FEEDBACK_SLOWER:
c++;
break;
case Feedback.FEEDBACK_AWAY:
d++;
break;
default:
break;
}
}
return new Feedback(a, b, c, d);
}
public Integer getMyFeedback(String keyword, User u) {
if (data.get(keyword) == null) {
return null;
}
for (FeedbackStorageObject fso : data.get(keyword).values()) {
if (fso.fromUser(u)) {
return fso.getValue();
}
}
return null;
}
public boolean saveFeedback(String keyword, int value, User user) {
if (dao.getSession(keyword) == null) {
throw new NotFoundException();
}
if (data.get(keyword) == null) {
data.put(keyword, new HashMap<String, FeedbackStorageObject>());
}
System.out.println(user.getUsername());
data.get(keyword).put(user.getUsername(), new FeedbackStorageObject(value, user));
return true;
}
public void cleanFeedbackVotes(int cleanupFeedbackDelay) {
for (String keyword : data.keySet()) {
this.cleanSessionFeedbackVotes(keyword, cleanupFeedbackDelay);
}
}
private void cleanSessionFeedbackVotes(String keyword, int cleanupFeedbackDelay) {
final long timelimitInMillis = 60000 * (long) cleanupFeedbackDelay;
final long maxAllowedTimeInMillis = System.currentTimeMillis() - timelimitInMillis;
Map<String, FeedbackStorageObject> sessionFeedbacks = data.get(keyword);
for (Map.Entry<String, FeedbackStorageObject> entry : sessionFeedbacks.entrySet()) {
if (
entry.getValue().getTimestamp().getTime() < maxAllowedTimeInMillis
) {
sessionFeedbacks.remove(entry.getKey());
}
}
}
}
......@@ -19,22 +19,21 @@
package de.thm.arsnova.services;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import javax.annotation.PostConstruct;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Service;
import de.thm.arsnova.FeedbackStorage;
import de.thm.arsnova.dao.IDatabaseDao;
import de.thm.arsnova.entities.Feedback;
import de.thm.arsnova.entities.User;
import de.thm.arsnova.events.ARSnovaEvent;
import de.thm.arsnova.events.Publisher;
import de.thm.arsnova.exceptions.NoContentException;
import de.thm.arsnova.socket.ARSnovaSocketIOServer;
......@@ -57,25 +56,32 @@ public class FeedbackService implements IFeedbackService {
@Autowired
private IUserService userService;
private FeedbackStorage feedbackStorage;
public final void setDatabaseDao(final IDatabaseDao newDatabaseDao) {
this.databaseDao = newDatabaseDao;
}
@PostConstruct
public void init() {
this.feedbackStorage = new FeedbackStorage(databaseDao);
}
@Override
@Scheduled(fixedDelay = DEFAULT_SCHEDULER_DELAY)
public final void cleanFeedbackVotes() {
databaseDao.cleanFeedbackVotes(cleanupFeedbackDelay);
feedbackStorage.cleanFeedbackVotes(cleanupFeedbackDelay);
}
@Override
public final Feedback getFeedback(final String keyword) {
return databaseDao.getFeedback(keyword);
return feedbackStorage.getFeedback(keyword);
}
@Override
public final int getFeedbackCount(final String keyword) {
Feedback feedback = databaseDao.getFeedback(keyword);
Feedback feedback = feedbackStorage.getFeedback(keyword);
List<Integer> values = feedback.getValues();
return values.get(Feedback.FEEDBACK_FASTER) + values.get(Feedback.FEEDBACK_OK)
+ values.get(Feedback.FEEDBACK_SLOWER) + values.get(Feedback.FEEDBACK_AWAY);
......@@ -83,7 +89,7 @@ public class FeedbackService implements IFeedbackService {
@Override
public final double getAverageFeedback(final String sessionkey) {
Feedback feedback = databaseDao.getFeedback(sessionkey);
Feedback feedback = feedbackStorage.getFeedback(sessionkey);
List<Integer> values = feedback.getValues();
double count = values.get(Feedback.FEEDBACK_FASTER) + values.get(Feedback.FEEDBACK_OK)
+ values.get(Feedback.FEEDBACK_SLOWER) + values.get(Feedback.FEEDBACK_AWAY);
......@@ -103,7 +109,7 @@ public class FeedbackService implements IFeedbackService {
@Override
public final boolean saveFeedback(final String keyword, final int value, final User user) {
boolean result = databaseDao.saveFeedback(keyword, value, user);
boolean result = feedbackStorage.saveFeedback(keyword, value, user);
if (result) {
this.server.reportUpdatedFeedbackForSession(keyword);
}
......@@ -138,91 +144,6 @@ public class FeedbackService implements IFeedbackService {
@Override
public final Integer getMyFeedback(final String keyword, final User user) {
return this.databaseDao.getMyFeedback(keyword, user);
}
private static class FeedbackStorageObject {
private int value;
private Date timestamp;
public FeedbackStorageObject(int initValue) {
this.value = initValue;
this.timestamp = new Date();
}
public int getValue() {
return value;
}
public Date getTimestamp() {
return timestamp;
}
}
private static class FeedbackStorage {
private Map<String, Map<String, FeedbackStorageObject>> data;
public FeedbackStorage() {
this.data = new HashMap<String, Map<String,FeedbackStorageObject>>();
}
public Feedback getFeedback(String keyword) {
int a = 0;
int b = 0;
int c = 0;
int d = 0;
if (data.get(keyword) == null) {
return new Feedback(0, 0, 0, 0);
}
for (FeedbackStorageObject fso : data.get(keyword).values()) {
switch (fso.getValue()) {
case Feedback.FEEDBACK_FASTER:
a++;
break;
case Feedback.FEEDBACK_OK:
b++;
break;
case Feedback.FEEDBACK_SLOWER:
c++;
break;
case Feedback.FEEDBACK_AWAY:
d++;
break;
default:
break;
}
}
return new Feedback(a, b, c, d);
}
public boolean saveFeedback(String keyword, int value, User user) {
if (data.get(keyword) == null) {
data.put(keyword, new HashMap<String, FeedbackStorageObject>());
}
data.get(keyword).put(user.getUsername(), new FeedbackStorageObject(value));
return true;
}
public void cleanFeedbackVotes(int cleanupFeedbackDelay) {
for (String keyword : data.keySet()) {
this.cleanSessionFeedbackVotes(keyword, cleanupFeedbackDelay);
}
}
private void cleanSessionFeedbackVotes(String keyword, int cleanupFeedbackDelay) {
final long timelimitInMillis = 60000 * (long) cleanupFeedbackDelay;
final long maxAllowedTimeInMillis = System.currentTimeMillis() - timelimitInMillis;
Map<String, FeedbackStorageObject> sessionFeedbacks = data.get(keyword);
for (Map.Entry<String, FeedbackStorageObject> entry : sessionFeedbacks.entrySet()) {
if (
entry.getValue().getTimestamp().getTime() < maxAllowedTimeInMillis
) {
sessionFeedbacks.remove(entry.getKey());
}
}
}
return this.feedbackStorage.getMyFeedback(keyword, user);
}
}
......@@ -88,7 +88,7 @@ public class UserSessionServiceImpl implements UserSessionService, Serializable
return result;
}
return null;
return new LoggedIn();
}
private boolean hasConnectedWebSocket() {
......
......@@ -20,6 +20,7 @@ import org.springframework.web.servlet.HandlerAdapter;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter;
import de.thm.arsnova.FeedbackStorage;
import de.thm.arsnova.dao.StubDatabaseDao;
import de.thm.arsnova.exceptions.NoContentException;
import de.thm.arsnova.exceptions.NotFoundException;
......@@ -47,6 +48,8 @@ public class FeedbackControllerTest {
@Autowired
private StubDatabaseDao databaseDao;
private FeedbackStorage feedbackStorage;
@After
public final void cleanup() {
......@@ -58,6 +61,7 @@ public class FeedbackControllerTest {
this.request = new MockHttpServletRequest();
this.response = new MockHttpServletResponse();
handlerAdapter = applicationContext.getBean(AnnotationMethodHandlerAdapter.class);
this.feedbackStorage = new FeedbackStorage(databaseDao);
}
@Test(expected = NotFoundException.class)
......@@ -105,6 +109,6 @@ public class FeedbackControllerTest {
handlerAdapter.handle(request, response, feedbackController);
assertTrue(response.getStatus() == 200);
assertEquals("{\"values\":[2,3,5,7]}", response.getContentAsString());
assertEquals("{\"values\":[0,0,0,0]}", response.getContentAsString());
}
}
......@@ -55,7 +55,7 @@ public class StatisticsControllerTest {
request.setRequestURI("/statistics/sessioncount");
handlerAdapter.handle(request, response, statisticsController);
assertEquals("2", response.getContentAsString());
assertEquals("3", response.getContentAsString());
}
@Test
......@@ -64,7 +64,7 @@ public class StatisticsControllerTest {
request.setRequestURI("/statistics/");
handlerAdapter.handle(request, response, statisticsController);
String expected = "{\"answers\":0,\"questions\":0,\"openSessions\":2,\"closedSessions\":0,\"activeUsers\":0}";
String expected = "{\"answers\":0,\"questions\":0,\"openSessions\":3,\"closedSessions\":0,\"activeUsers\":0}";
assertEquals(expected, response.getContentAsString());
}
}
......@@ -87,6 +87,15 @@ public class StubDatabaseDao implements IDatabaseDao {
session.setShortName("TS2");
stubSessions.put("87654321", session);
session = new Session();
session.setActive(true);
session.setCreator("ptsr00");
session.setKeyword("18273645");
session.setName("TestSession2");
session.setShortName("TS3");
stubSessions.put("18273645", session);
}
private void fillWithDummyFeedbacks() {
......
......@@ -22,13 +22,16 @@ import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import de.thm.arsnova.dao.StubDatabaseDao;
import de.thm.arsnova.entities.User;
import de.thm.arsnova.exceptions.NoContentException;
import de.thm.arsnova.exceptions.NotFoundException;
......@@ -49,6 +52,53 @@ public class FeedbackServiceTest {
@Autowired
private StubDatabaseDao databaseDao;
@Before
public final void setup() {
userService.setUserAuthenticated(false);
feedbackService.saveFeedback("87654321", 0, new TestUser("testuser01"));
feedbackService.saveFeedback("87654321", 0, new TestUser("testuser02"));
feedbackService.saveFeedback("87654321", 1, new TestUser("testuser11"));
feedbackService.saveFeedback("87654321", 1, new TestUser("testuser12"));
feedbackService.saveFeedback("87654321", 1, new TestUser("testuser13"));
feedbackService.saveFeedback("87654321", 2, new TestUser("testuser21"));
feedbackService.saveFeedback("87654321", 2, new TestUser("testuser22"));
feedbackService.saveFeedback("87654321", 2, new TestUser("testuser23"));
feedbackService.saveFeedback("87654321", 2, new TestUser("testuser24"));
feedbackService.saveFeedback("87654321", 2, new TestUser("testuser25"));
feedbackService.saveFeedback("87654321", 3, new TestUser("testuser31"));
feedbackService.saveFeedback("87654321", 3, new TestUser("testuser32"));
feedbackService.saveFeedback("87654321", 3, new TestUser("testuser33"));
feedbackService.saveFeedback("87654321", 3, new TestUser("testuser34"));
feedbackService.saveFeedback("87654321", 3, new TestUser("testuser35"));
feedbackService.saveFeedback("87654321", 3, new TestUser("testuser36"));
feedbackService.saveFeedback("87654321", 3, new TestUser("testuser37"));
feedbackService.saveFeedback("18273645", 0, new TestUser("testuser01"));
feedbackService.saveFeedback("18273645", 0, new TestUser("testuser02"));
feedbackService.saveFeedback("18273645", 1, new TestUser("testuser11"));
feedbackService.saveFeedback("18273645", 1, new TestUser("testuser12"));
feedbackService.saveFeedback("18273645", 1, new TestUser("testuser13"));
feedbackService.saveFeedback("18273645", 2, new TestUser("testuser21"));
feedbackService.saveFeedback("18273645", 2, new TestUser("testuser22"));
feedbackService.saveFeedback("18273645", 2, new TestUser("testuser23"));
feedbackService.saveFeedback("18273645", 2, new TestUser("testuser24"));
feedbackService.saveFeedback("18273645", 2, new TestUser("testuser25"));
feedbackService.saveFeedback("18273645", 3, new TestUser("testuser31"));
feedbackService.saveFeedback("18273645", 3, new TestUser("testuser32"));
feedbackService.saveFeedback("18273645", 3, new TestUser("testuser33"));
feedbackService.saveFeedback("18273645", 3, new TestUser("testuser34"));
feedbackService.saveFeedback("18273645", 3, new TestUser("testuser35"));
feedbackService.saveFeedback("18273645", 3, new TestUser("testuser36"));
feedbackService.saveFeedback("18273645", 3, new TestUser("testuser37"));
feedbackService.saveFeedback("18273645", 3, new TestUser("testuser38"));
feedbackService.saveFeedback("18273645", 3, new TestUser("testuser39"));
feedbackService.saveFeedback("18273645", 3, new TestUser("testuser310"));
feedbackService.saveFeedback("18273645", 3, new TestUser("testuser311"));
}
@After
public final void cleanup() {
databaseDao.cleanupTestData();
......@@ -112,4 +162,15 @@ public class FeedbackServiceTest {
userService.setUserAuthenticated(true);
assertEquals(2.1904, feedbackService.getAverageFeedback("18273645"), 0.001);
}
public static class TestUser extends User {
private static final long serialVersionUID = 1L;
private String username;
private String type;
public TestUser(String username) {
super( new UsernamePasswordAuthenticationToken(username, "secret") );
}
}
}
\ No newline at end of file
......@@ -67,7 +67,7 @@ public class StatisticsServiceTest {
@Test
public final void testShouldReturnStatistics() {
Statistics actual = statisticsService.getStatistics();
assertEquals(2, actual.getOpenSessions());
assertEquals(3, actual.getOpenSessions());
assertEquals(1, actual.getClosedSessions());
}
}
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment