Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ public class StatBuilderService {

private static Logger logger = Logger.getLogger(StatBuilderService.class);
private static Map<String, Map<String, Map<StatGranularity, Map<Instant, Stat>>>> stats;
private static boolean startedService = false;
private static volatile boolean startedService = false;


public boolean isDebugEnabled() {
Expand Down Expand Up @@ -311,8 +311,9 @@ public Stat getStat(String statClass, String entityId, StatGranularity statGranu
if (raceStat == null) {
dateStats.put(stateDateTime, stat);
if (this.isDebugEnabled()) logger.info("getStat: CREATED: entityId: " + entityId + " stat: " + stat + " stateDateTime: " + stateDateTime + " statGranularity: " + statGranularity);
} {
logger.warn("getStat: Not CREATED: entityId: " + entityId + " stat: " + stat + " stateDateTime: " + stateDateTime + " statGranularity: " + statGranularity);
} else {
stat = raceStat;
if (this.isDebugEnabled()) logger.info("getStat: Not CREATED, using cached race winner: entityId: " + entityId + " stat: " + stat + " stateDateTime: " + stateDateTime + " statGranularity: " + statGranularity);
}

}
Expand All @@ -336,10 +337,12 @@ public boolean isStartedService() {
}


public void init(ZoneId tz) {
public synchronized void init(ZoneId tz) {
this.tz = tz;

stats = new ConcurrentHashMap<String, Map<String, Map<StatGranularity, Map<Instant, Stat>>>>(5);
if (stats == null) {
stats = new ConcurrentHashMap<String, Map<String, Map<StatGranularity, Map<Instant, Stat>>>>(5);
}
//em.find(Stat.class, "1");
}

Expand Down
18 changes: 16 additions & 2 deletions src/main/java/com/mobiera/ms/commons/stats/svc/StatController.java
Original file line number Diff line number Diff line change
Expand Up @@ -78,14 +78,28 @@ public class StatController {

private static final Logger logger = Logger.getLogger("StatController");

private static boolean startedPurge = true;
private static volatile boolean startedPurge = true;

private boolean finished = false;
private volatile boolean finished = false;

void onStart(@Observes StartupEvent ev) {
logger.info("onStart: starting");
//startStatConsumers();

// Initialize the timezone and the in-memory stats map BEFORE marking the
// service as started, otherwise consumer threads can observe
// startedService==true and call getStat() while stats is still null (NPE),
// since startPurgeTask() runs asynchronously on the worker pool.
if (tz == null) {
try {
tz = ZoneId.of(timezoneName);
} catch (Exception e) {
logger.error("onStart: invalid com.mobiera.ms.commons.stats.timezone: " + timezoneName);
throw(e);
}
}
statService.init(tz);

startPurgeTask();
statService.setStartedService(true);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -66,15 +66,17 @@ public class StatReaderService {
@ConfigProperty(name = "com.mobiera.ms.commons.stats.in.memory.past.units")
Integer inMemoryPastUnits;

private static NumberFormat nf = null;
// NumberFormat is not thread-safe; the reader service is hit by multiple
// concurrent REST threads, so use a per-thread instance.
private static final ThreadLocal<NumberFormat> nf = ThreadLocal.withInitial(() -> {
NumberFormat instance = NumberFormat.getInstance();
instance.setMaximumIntegerDigits(20);
instance.setMaximumFractionDigits(2);
return instance;
});

private NumberFormat getNf() {
if (nf == null) {
nf = NumberFormat.getInstance();
nf.setMaximumIntegerDigits(20);
nf.setMaximumFractionDigits(2);
}
return nf;
return nf.get();
}

private List<String> buildHeader(List<StatEnum> enums) {
Expand Down
Loading