-
Notifications
You must be signed in to change notification settings - Fork 35
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add consensusj-analytics and build with JDK 11
* Add consensusj-analytics module which requires JDK 11 * Disable asciidoclet :-( * Drop modularity (for now) in consensusj-jsonrpc-cli
- Loading branch information
1 parent
a6ade0d
commit e51c0de
Showing
22 changed files
with
646 additions
and
53 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -21,4 +21,4 @@ script: | |
jdk: | ||
- openjdk8 | ||
- openjdk9 | ||
#- openjdk11 OpenJDK 11 disabled until we upgrade AsciiDoclet | ||
- openjdk11 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
plugins { | ||
id 'java-library' | ||
} | ||
|
||
sourceCompatibility = 11 | ||
targetCompatibility = 11 | ||
|
||
dependencies { | ||
api "io.reactivex.rxjava3:rxjava:${rxJavaVersion}" | ||
api "${bitcoinjGroup}:${bitcoinjArtifact}:${bitcoinjVersion}" | ||
|
||
// For annotations on TokenRichList | ||
//api "com.fasterxml.jackson.core:jackson-core:${jacksonVersion}" | ||
//api "com.fasterxml.jackson.core:jackson-databind:${jacksonVersion}" | ||
|
||
} | ||
|
||
ext.moduleName = 'org.consensusj.analytics' | ||
|
||
tasks.withType(JavaCompile) { | ||
options.compilerArgs << '-parameters' // Required for Jackson ParameterNamesModule | ||
} | ||
|
||
jar { | ||
inputs.property("moduleName", moduleName) | ||
manifest { | ||
attributes 'Automatic-Module-Name': moduleName, | ||
'Implementation-Version': archiveVersion.get() | ||
} | ||
} |
31 changes: 31 additions & 0 deletions
31
consensusj-analytics/src/main/java/org/consensusj/analytics/service/RichListService.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
package org.consensusj.analytics.service; | ||
|
||
import io.reactivex.rxjava3.core.Observable; | ||
import io.reactivex.rxjava3.core.Single; | ||
|
||
/** | ||
* Interface for reactive rich list service | ||
* | ||
* @param <N> Numeric type for balances | ||
* @param <ID> Type for currency identifiers (e.g. String, Omni Currency ID, etc) | ||
*/ | ||
public interface RichListService<N extends Number & Comparable<? super N>, ID> { | ||
|
||
/** | ||
* Return a single rich list | ||
* | ||
* @param currencyID The currency ID | ||
* @param numEntries The requested number of entries in the list | ||
* @return An RxJava single for lazy access to the response | ||
*/ | ||
Single<TokenRichList<N, ID>> richList(ID currencyID, int numEntries); | ||
|
||
/** | ||
* Get a continuous stream of rich list updates | ||
* | ||
* @param currencyID The currency ID | ||
* @param numEntries The requested number of entries in each list | ||
* @return An RxJava Observable for lazy access to the stream | ||
*/ | ||
Observable<TokenRichList<N, ID>> richListUpdates(ID currencyID, int numEntries); | ||
} |
76 changes: 76 additions & 0 deletions
76
consensusj-analytics/src/main/java/org/consensusj/analytics/service/TokenRichList.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,76 @@ | ||
package org.consensusj.analytics.service; | ||
|
||
import org.bitcoinj.core.Address; | ||
import org.bitcoinj.core.Sha256Hash; | ||
|
||
import java.util.List; | ||
|
||
/** | ||
* Response format for Omni rich list queries. | ||
* | ||
* TODO: Jackson annotations? | ||
*/ | ||
public class TokenRichList<N extends Number & Comparable<? super N>, ID> { | ||
private final int blockHeight; | ||
private final Sha256Hash blockHash; | ||
private final long timestamp; | ||
private final ID currencyID; | ||
private final List<TokenBalancePair<N>> richList; | ||
private final N otherBalanceTotal; | ||
|
||
public TokenRichList(int blockHeight, | ||
Sha256Hash blockHash, | ||
long timestamp, | ||
ID currencyID, | ||
List<TokenBalancePair<N>> richList, | ||
N otherBalanceTotal) { | ||
this.blockHeight = blockHeight; | ||
this.blockHash = blockHash; | ||
this.timestamp = timestamp; | ||
this.currencyID = currencyID; | ||
this.richList = List.copyOf(richList); | ||
this.otherBalanceTotal = otherBalanceTotal; | ||
} | ||
|
||
public static class TokenBalancePair<N extends Number & Comparable<? super N>> { | ||
private final Address address; | ||
private final N balance; | ||
|
||
public TokenBalancePair(Address address, N balance) { | ||
this.address = address; | ||
this.balance = balance; | ||
} | ||
|
||
public Address getAddress() { | ||
return address; | ||
} | ||
|
||
public N getBalance() { | ||
return balance; | ||
} | ||
} | ||
|
||
public int getBlockHeight() { | ||
return blockHeight; | ||
} | ||
|
||
public Sha256Hash getBlockHash() { | ||
return blockHash; | ||
} | ||
|
||
public long getTimestamp() { | ||
return timestamp; | ||
} | ||
|
||
public ID getCurrencyID() { | ||
return currencyID; | ||
} | ||
|
||
public List<TokenBalancePair<N>> getRichList() { | ||
return richList; | ||
} | ||
|
||
public N getOtherBalanceTotal() { | ||
return otherBalanceTotal; | ||
} | ||
} |
123 changes: 123 additions & 0 deletions
123
...lytics/src/main/java/org/consensusj/analytics/util/collector/LargestSliceAccumulator.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,123 @@ | ||
package org.consensusj.analytics.util.collector; | ||
|
||
import org.slf4j.Logger; | ||
import org.slf4j.LoggerFactory; | ||
|
||
import java.util.AbstractQueue; | ||
import java.util.Comparator; | ||
import java.util.List; | ||
import java.util.PriorityQueue; | ||
import java.util.function.BinaryOperator; | ||
import java.util.function.Function; | ||
import java.util.stream.Collectors; | ||
|
||
/** | ||
* Accumulates the {@code n} largest slices of a stream of objects of type {@code <E>}. Uses a {@link PriorityQueue} | ||
* implementation of {@link AbstractQueue} internally. | ||
* <p> | ||
* This class is <b>not</b> thread-safe and is <b>not</b> designed for use with a {@link java.util.stream.Collector.Characteristics#CONCURRENT} | ||
* {@link java.util.stream.Collector}. Switching the {@link AbstractQueue} implementation to {@link java.util.concurrent.PriorityBlockingQueue} | ||
* will work (with reduced performance) but the implementations of {@link #accumulate(Object)}, {@link #combine(LargestSliceAccumulator)}, | ||
* and {@link #drain()} are not thread-safe. Even if this class were thread-safe, enabling {@code CONCURRENT} | ||
* in a {@code Collector} using this class would <b>reduce</b> performance because multiple threads would be trying to merge Objects | ||
* into the same accumulator. The optimal way to use this class is with one accumulator per thread | ||
* and this is what Collector will do without the {@code CONCURRENT} flag. | ||
* | ||
* @param <E> must be comparable because it is the second sort field | ||
* @param <N> numeric type for Slice Size | ||
*/ | ||
public final class LargestSliceAccumulator<E, N extends Number & Comparable<? super N>> { | ||
private static final Logger log = LoggerFactory.getLogger(LargestSliceAccumulator.class); | ||
private final int n; // Maximum number of slices to track | ||
private final Function<E, N> sliceSizeExtractor; | ||
private final BinaryOperator<N> additionOperator; | ||
private final AbstractQueue<E> sliceQueue; | ||
private final Comparator<E> comparator; | ||
private N otherTotal; | ||
|
||
/** | ||
* Construct | ||
* @param n maximum number of keys (addresses) to track | ||
* @param sliceSizeExtractor Function to compute the slice size | ||
* @param zero The value zero for type N | ||
* @param additionOperator binary addition operator for type N | ||
*/ | ||
public LargestSliceAccumulator(int n, | ||
Function<E, N> sliceSizeExtractor, | ||
N zero, | ||
BinaryOperator<N> additionOperator) { | ||
if (n < 1) { | ||
throw new IllegalArgumentException("parameter must be 1 or greater"); | ||
} | ||
this.n = n; | ||
this.sliceSizeExtractor = sliceSizeExtractor; | ||
this.additionOperator = additionOperator; | ||
this.otherTotal = zero; | ||
this.comparator = Comparator.comparing(sliceSizeExtractor); | ||
log.trace("Creating accum queue"); | ||
sliceQueue = new PriorityQueue<>(n, Comparator.comparing(sliceSizeExtractor)); | ||
} | ||
|
||
/** | ||
* Add a new slice to the accumulator | ||
* | ||
* @param newSlice slice to accumulate | ||
*/ | ||
void accumulate(E newSlice) { | ||
//log.trace("accumulating slice of size: {}", sliceSizeExtractor.apply(newSlice).doubleValue()); | ||
sliceQueue.add(newSlice); | ||
drain(); // Remove extra elements. | ||
} | ||
|
||
/** | ||
* Combine two accumulators | ||
* | ||
* @param other the other accumulator | ||
* @return the combined accumulator (this) | ||
*/ | ||
LargestSliceAccumulator<E, N> combine(LargestSliceAccumulator<E, N > other) { | ||
other.sliceQueue.forEach(this::accumulate); | ||
otherTotal = plus(otherTotal, other.otherTotal); | ||
return this; | ||
} | ||
|
||
// It's simpler (and possibly faster) to let the queue do the size comparison | ||
// and just remove extra elements rather than implement our own checks _before_ | ||
// adding to the queue. | ||
private void drain() { | ||
while (sliceQueue.size() > n) { | ||
E removed = sliceQueue.poll(); | ||
if (removed != null) { | ||
otherTotal = plus(otherTotal, sliceSizeExtractor.apply(removed)); | ||
} | ||
} | ||
} | ||
|
||
/** | ||
* Sort the sliceQueue and return as a {@link List}. | ||
* Normally, This should only be called by the Collector finisher function. | ||
* | ||
* @return List of slices sorted by their slice size (based on extractor) | ||
*/ | ||
List<E> getSortedSliceList() { | ||
// E[] tmp = (E[]) sliceQueue.toArray(); // Copies to an array | ||
// Arrays.sort(tmp, comparator); // Sorts the array | ||
// return List.of(tmp); // Copy into a list | ||
return sliceQueue.stream() | ||
.sorted(comparator) | ||
.collect(Collectors.toUnmodifiableList()); | ||
} | ||
|
||
/** | ||
* Get the total "slice size" of processed elements that are not saved in this accumulator. | ||
* | ||
* @return total slice size of other elements. | ||
*/ | ||
N getTotalOther() { | ||
return otherTotal; | ||
} | ||
|
||
private N plus(N n1, N n2) { | ||
return additionOperator.apply(n1, n2); | ||
} | ||
} |
Oops, something went wrong.