How to use Queue in StackExchange.Redis - stackexchange.redis

I am confused about how to use Queue in StackExchange.Redis.
I have tried download the source code and check the documentation.
I still can not find how to use it.
please give me suggestion.
thanks very much.

Redis supports both queues and stacks through the LPUSH, LPOP, RPUSH and RPOP commands. It is just a matter of calling the right operations on a list. Below are sample implementations of a queue and a stack as a reference. "Connection" in the code below is just an instance of a ConnectionMultiplexer
static class RedisStack
{
public static void Push(RedisKey stackName, RedisValue value)
{
Connection.GetDatabase().ListRightPush(stackName, value);
}
public static RedisValue Pop(RedisKey stackName)
{
return Connection.GetDatabase().ListRightPop(stackName);
}
}
static class RedisQueue
{
public static void Push(RedisKey queueName, RedisValue value)
{
Connection.GetDatabase().ListRightPush(queueName, value);
}
public static RedisValue Pop(RedisKey queueName)
{
return Connection.GetDatabase().ListLeftPop(queueName);
}
}

Related

can TextWebSocketFrame be declared with static and final?

In Netty, send messages are like this:
channel.writeAndFlush(new TextWebSocketFrame("Operation Succeed"));
to run this code, nothing abnormal. so I think, argument from writeAndFlush can be extracted to a static and final variable like this:
public class LogicHandler extends SimpleUserEventChannelHandler<WebSocketServerProtocolHandler.HandshakeComplete> {
static final TextWebSocketFrame SUCCEED = new TextWebSocketFrame("Operation Succeed");
#Override
protected void eventReceived(ChannelHandlerContext context, WebSocketServerProtocolHandler.HandshakeComplete arg) {
context.channel().writeAndFlush(SUCCEED.retain()); // the client received empty content
}
}
to run this codes,
abnormal things happen:
the client(WebSocket from Chrome browser) received the message but empty content
Are there any ideas that i can do with it?
remove the method "retain" can not solve the problem, the only way is to remove static and final keyword.
Because the underlying ByteBuf's readerIndex is updated once used. You can reuse it by reset the readerIndex, like below. But this code is thread-unsafe, it can cause problems when there are multiple connections.
public static class LogicHandler extends SimpleUserEventChannelHandler<WebSocketServerProtocolHandler.HandshakeComplete> {
static final TextWebSocketFrame SUCCEED = new TextWebSocketFrame("Operation Succeed");
#Override
protected void eventReceived(ChannelHandlerContext context, WebSocketServerProtocolHandler.HandshakeComplete arg) {
SUCCEED.content().readerIndex(0);
context.channel().writeAndFlush(SUCCEED.retain());
}
}
This is thread-safe
public static class LogicHandler extends SimpleUserEventChannelHandler<WebSocketServerProtocolHandler.HandshakeComplete> {
static final TextWebSocketFrame SUCCEED = new TextWebSocketFrame("Operation Succeed");
#Override
protected void eventReceived(ChannelHandlerContext context, WebSocketServerProtocolHandler.HandshakeComplete arg) {
context.channel().writeAndFlush(SUCCEED.retainedDuplicate());
}
}

Vert.x aerospike client to use context-bound event loop

Standard java aerospike client's methods have overloads allowing to provide EventLoop as an argument. When running in vert.x that client is not aware of context-bounded event loop and just fallbacks to if (eventLoop == null) { eventLoop = cluster.eventLoops.next(); } which could(and likely does) causes context switching/level of concurrency which in turn affects performance (it's still in theory, but I want to prove it), because there is no guarantee that aerospike requests will run on the same event loop as coming http request according to Vert.x Multi Reactor pattern. Open source aerospike clients like vertx-aerospike-client also have such a disadvantage. Using vert.x there is no way(at least I'm not aware of) to retrieve context-bounded event loop and pass it to aerospike client.
Vert.x has method to retrieve Context Vertx.currentContext() but retrieving EventLoop is not available.
Any ideas?
Finally I've built this:
public class ContextEventLoop {
private final NettyEventLoops eventLoops;
public ContextEventLoop(final NettyEventLoops eventLoops) {
this.eventLoops = Objects.requireNonNull(eventLoops, "eventLoops");
}
public EventLoop resolve() {
final ContextInternal ctx = ContextInternal.current();
final EventLoop eventLoop;
if (ctx != null
&& ctx.isEventLoopContext()
&& (eventLoop = eventLoops.get(ctx.nettyEventLoop())) != null) {
return eventLoop;
}
return eventLoops.next();
}
}
#NotNull
public EventLoops wrap(final EventLoops fallback,
final Supplier<#NotNull EventLoop> next) {
return new EventLoops() {
#Override
public EventLoop[] getArray() {
return fallback.getArray();
}
#Override
public int getSize() {
return fallback.getSize();
}
#Override
public EventLoop get(int index) {
return fallback.get(index);
}
#Override
public EventLoop next() {
return next.get();
}
#Override
public void close() {
fallback.close();
}
};
}

Java8 to Java7 - Migrate Comparators

I'm having troubles understanding how to "migrate" a simple Comparator in Java7.
The actual version I'm using in Java8 is like:
private static final Comparator<Entry> ENTRY_COMPARATOR = Comparator.comparing(new Function<Entry, EntryType>() {
#Override
public EntryType apply(Entry t) {
return t.type;
}
})
.thenComparing(Comparator.comparingLong(new ToLongFunction<Entry>() {
#Override
public long applyAsLong(Entry value) {
return value.count;
}
}).reversed());
But in build phase I get this error:
static interface method invocations are not supported in -source 7
How can I migrate the same comparator to Java7? I'm googling and searching for solution but the only thing I can think of, is to implement my own class as a Comparator interface implementation.
But If I go down that road, how can I apply both "comparing", "then comparing" and "reverse" in the same "compare" method?
Thanks in advance
Even your java-8 version can be made a lot shorter and easier to read with:
Comparator.comparing(Entry::getType)
.thenComparingLong(Entry::getCount)
.reversed();
With guava (java-7 compatible), this looks a bit more verbose:
#Override
public int compare(Entry left, Entry right) {
return ComparisonChain.start()
.compare(left.getType(), right.getCount(), Ordering.natural().reversed())
.compare(left.getCount(), right.getCount(), Ordering.natural().reversed())
.result();
}
You can write the logic in a single compare method:
public int compare (Entry one,Entry two) {
int result = two.getType().compareTo(one.getType());
if (result == 0) {
result = Long.compare(two.getCount(),one.getCount());
}
return result;
}
Note that the reversed order in achieved by swapping the order of the compared Entry instances.
You can construct a Comparator<Entry> the java 7 way, afterward, you can chain the default methods as you can do in java 8, but without using lambda expressions or method references as a parameter :
private static final Comparator<Entry> ENTRY_COMPARATOR = new Comparator<Entry>() {
#Override
public int compare(Entry left, Entry right) {
return left.type.compareTo(right.type);
}
}
.thenComparingLong(new ToLongFunction<Entry>() {
#Override
public long applyAsLong(Entry entry) {
return entry.value;
}
})
.reversed();
The code above is compiled with -source 1.7.

Mockito: Verifying a method was called with a functional parameter

I have a simple scenario in which am trying to verify some behavior when a method is called (i.e. that a certain method was called with given parameter, a function pointer in this scenario). Below are my classes:
#SpringBootApplication
public class Application {
public static void main(String[] args) {
ConfigurableApplicationContext context = SpringApplication.run(Application.class, args);
AppBootStrapper bootStrapper = context.getBean(AppBootStrapper.class);
bootStrapper.start();
}
}
#Component
public class AppBootStrapper {
private NetworkScanner networkScanner;
private PacketConsumer packetConsumer;
public AppBootStrapper(NetworkScanner networkScanner, PacketConsumer packetConsumer) {
this.networkScanner = networkScanner;
this.packetConsumer = packetConsumer;
}
public void start() {
networkScanner.addConsumer(packetConsumer::consumePacket);
networkScanner.startScan();
}
}
#Component
public class NetworkScanner {
private List<Consumer<String>> consumers = new ArrayList<>();
public void startScan(){
Executors.newSingleThreadExecutor().submit(() -> {
while(true) {
// do some scanning and get/parse packets
consumers.forEach(consumer -> consumer.accept("Package Data"));
}
});
}
public void addConsumer(Consumer<String> consumer) {
this.consumers.add(consumer);
}
}
#Component
public class PacketConsumer {
public void consumePacket(String packet) {
System.out.println("Packet received: " + packet);
}
}
#RunWith(JUnit4.class)
public class AppBootStrapperTest {
#Test
public void start() throws Exception {
NetworkScanner networkScanner = mock(NetworkScanner.class);
PacketConsumer packetConsumer = mock(PacketConsumer.class);
AppBootStrapper appBootStrapper = new AppBootStrapper(networkScanner, packetConsumer);
appBootStrapper.start();
verify(networkScanner).addConsumer(packetConsumer::consumePacket);
verify(networkScanner, times(1)).startScan();
}
}
I want to verify that bootStrapper did in fact do proper setup by registering the packet consumer(there might be other consumers registered later on, but this one is mandatory) and then called startScan. I get the following error message when I execute the test case:
Argument(s) are different! Wanted:
networkScanner bean.addConsumer(
com.spring.starter.AppBootStrapperTest$$Lambda$8/438123546#282308c3
);
-> at com.spring.starter.AppBootStrapperTest.start(AppBootStrapperTest.java:24)
Actual invocation has different arguments:
networkScanner bean.addConsumer(
com.spring.starter.AppBootStrapper$$Lambda$7/920446957#5dda14d0
);
-> at com.spring.starter.AppBootStrapper.start(AppBootStrapper.java:12)
From the exception, clearly the function pointers aren't the same.
Am I approaching this the right way? Is there something basic I am missing? I played around and had a consumer injected into PacketConsumer just to see if it made a different and that was OK, but I know that's certainly not the right way to go.
Any help, perspectives on this would be greatly appreciated.
Java doesn't have any concept of "function pointers"; when you see:
networkScanner.addConsumer(packetConsumer::consumePacket);
What Java actually compiles is (the equivalent of):
networkScanner.addConsumer(new Consumer<String>() {
#Override void accept(String packet) {
packetConsumer.consumePacket(packet);
}
});
This anonymous inner class happens to be called AppBootStrapper$$Lambda$7. Because it doesn't (and shouldn't) define an equals method, it will never be equal to the anonymous inner class that the compiler generates in your test, which happens to be called AppBootStrapperTest$$Lambda$8. This is regardless of the fact that the method bodies are the same, and are built in the same way from the same method reference.
If you generate the Consumer explicitly in your test and save it as a static final Consumer<String> field, then you can pass that reference in the test and compare it; at that point, reference equality should hold. This should work with a lambda expression or method reference just fine.
A more apt test would probably verify(packetConsumer, atLeastOnce()).consumePacket(...), as the contents of the lambda are an implementation detail and you're really more concerned about how your component collaborates with other components. The abstraction here should be at the consumePacket level, not at the addConsumer level.
See the comments and answer on this SO question.

How can I access previously set fields in a seam #Observer method?

My current setup is JBoss Seam 2.2 on JBoss 4.2.3.GA.
I have two Beans like so:
#Name("mailingManager")
#Scope(ScopeType.PAGE)
public class MailingMgr {
private Mailing selectedMailing;
#Observer("mailing.letter.success")
public void recordSuccess(final Object arg) {
if (null != selectedMailing) { // store arg }
}
public void send() {
selectedMailing = new Mailing();
if ('EMAIL' == determineType()) {
EmailSender mailer = (EmailSender) Component.getInstance(EmailSender.class);
mailer.send(getAddresses());
}
// ... more options
}
}
#Name("emailSender")
#Scope(ScopeType.PAGE)
public class EmailSender {
public void send(final Set<String> addresses) {
for (String addr : addresses) {
// ... create a mail
Events.instance().raiseEvent("mailing.letter.success", getGeneratedMail());
}
}
}
The problem is that when recordSuccess() is called selectedMailing is always null.
As a workaround I'm setting selectedMailing in the conversation context manually before calling any code that could potentially trigger my events, and then annotate my field with #In(required=false) to inject it again before recordSuccess is called. But is there a more elegant solution (keeping the decoupling intact)? And why isn't the calling bean reused to handle the event?

Resources