Google pubsub listener not receiving all the messages - google-cloud-storage

I'm using Google Cloud Storage for storing objects, with the bucket associated to a topic and subscription id. The flow is such that a Java application requests for the upload link(s), and upload object(s) using those upload link(s). I also have a pubsub listener implemented in Java, which receives the upload notification message, and does something on every successful upload. This is the snippet that handles the event listening.
public void eventListener() {
MessageReceiver messageReceiver = (message, consumer) -> {
final Map<String, Object> uploadMetaDataMap = getUploadDataMap(message);
LOGGER.info("Upload event detected => {} ", uploadMetaDataMap);
// do something
consumer.ack();
};
Subscriber subscriber = null;
Subscriber finalSubscriber = subscriber;
/* To ensure that any messages already being handled by receiveMessage run to completion */
Runtime.getRuntime().addShutdownHook(new Thread() {
#Override
public void run() {
finalSubscriber.stopAsync().awaitTerminated();
}
});
try {
subscriber = Subscriber.newBuilder(subscription, messageReceiver)
.setCredentialsProvider(FixedCredentialsProvider.create(creds)).build();
subscriber.addListener(new Subscriber.Listener() {
#Override
public void failed(Subscriber.State from, Throwable failure) {
// Handle failure. This is called when the Subscriber encountered a fatal error and is shutting down.
LOGGER.error(String.valueOf(failure));
}
}, MoreExecutors.directExecutor());
subscriber.startAsync().awaitRunning();
subscriber.awaitTerminated();
} finally {
if (subscriber != null) {
subscriber.stopAsync().awaitTerminated();
}
}
}
I'm storing the objects in this format => bucket/uuid/objectName.extension and on every successful upload, LOGGER.info("Upload event detected => {} ", uploadMetaDataMap); logs messages like this
2020-08-03 16:12:14,686 [Gax-1] INFO listener.AsynchronousPull - Upload event detected => {size=85, uuid=6dff9a20-3995-4f28-93e9-79e6c3cf613d, bucket=bucketName}
The issue I'm facing now is, not all the successful upload events send out notification message. I can see the folder structure created in the GCS with the respective object inside it, but notification related to that upload is nowhere to be found in the logs printed by pubsub listener. It's been bothering me for a while now, and could really use some help with this.

Related

How to know who received a message in a MUC room

For my thesis, I am using Smack to log a XMPP network that uses the MUC module.
Another software is currently sending IoT sensor data into different MUC rooms.
I'd like to know for every message sent into a MUC room, which users were in that room at the time of the message. Is this possible? I could use a messageListener to every muc room, however the listener only receives a message as an argument. Therefore I could not know who is logged into the room inside the listener method.
you can get all muc message in StanzaListener in xmpp. Please follow few steps to done this
Step 1. Declare as a global variables
ChatManagerListener chatListener;
Chat chat;
StanzaListener packetListener;
Step 2. Use this code in oncreate or in fragment
Note: Make sure you have connected with chat server.
packetListener = new StanzaListener() {
#Override
public void processPacket(Stanza packet) throws SmackException.NotConnectedException, InterruptedException {
if (packet instanceof Message) {
final Message message = (Message) packet;
}
}
};
XMPP.getInstance().getConnection(acitiviy)).addAsyncStanzaListener(stanzaListener, null);
ServiceDiscoveryManager sdm = ServiceDiscoveryManager
.getInstanceFor(XMPP.getInstance().getConnection(acitiviy)));
sdm.addFeature("jabber.org/protocol/si");
sdm.addFeature("http://jabber.org/protocol/si");
sdm.addFeature("http://jabber.org/protocol/disco#info");
sdm.addFeature("jabber:iq:privacy");
Step 3. Methods for one to one chat purposer
void sendMessage(String message) {
if (chat != null) {
try {
chat.sendMessage(message);
Message msg = new Message();
msg.setTo(JidCreate.bareFrom(jid));
msg.setFrom(XMPP.getInstance().getConnection(acitiviy)
.getUser());
ChatStateExtension ext = new ChatStateExtension(
ChatState.paused);
msg.addExtension(ext);
lastComposing = System.currentTimeMillis();
chat.sendMessage(msg);
} catch (SmackException.NotConnectedException e) {
} catch (Exception e) {
}
}
}
Step 4. On destroy
XMPP.getInstance().getConnection(acitiviy)).removeAsyncStanzaListener(stanzaListener);
Hope this will help you and if you want more information take a look from here. Thankyou
Nothing prervents you from calling Multi UserCaht.getParticipants() from within the listener. But be warned: If your goal is to determine the other receivers of receivers, then this approach is fragile. I also suggest to think about using PubSub instead of MUC for your IoT use case.

Redux-saga and socket subscription causes Uncaught TypeError: Converting circular structure to JSON

I am having trouble subscribing to a socketcluster (http://socketcluster.io/) channel when using a redux-saga generator in my chat app. The socketcluster backend is setup in a way where any messages are saved in the database then published into the receiving user's personal channel, which is named after the user's id. For example, User A has an id '123abc' and would subscribe to the channel named '123abc' for their realtime messages.
The code below does receive new messages that are published to a channel but it throws a "TypeError: Converting circular structure to JSON" onload and breaks all of my other redux-saga generators in the app. I've done digging in Chrome Devtools and my theory is that it has something to do with queue created in the createChannel function. Also, I've tried returning a deferred promise in the subscribeToChannel function but that also caused a Circular Conversion Error, I can post that code on request.
I referred to this answer at first: https://stackoverflow.com/a/35288877/5068616 and it helped me get the below code in place but I cannot find any similar issues on the internet. Also something to note, I am utilizing redux-socket-cluster (https://github.com/mattkrick/redux-socket-cluster) to sync up the socket and state, but I don't think it is the root of the problem
sagas.js
export default function* root() {
yield [
fork(startSubscription),
]
}
function* startSubscription(getState) {
while (true) {
const {
userId
} = yield take(actions.SUBSCRIBE_TO_MY_CHANNEL);
yield call(monitorChangeEvents, subscribeToChannel(userId))
}
}
function* monitorChangeEvents(channel) {
while (true) {
const info = yield call(channel.take) // Blocks until the promise resolves
console.log(info)
}
}
function subscribeToChannel(channelName) {
const channel = createChannel();
const socket = socketCluster.connect(socketConfig);
const c = socket.subscribe(channelName);
c.watch(event => {
channel.put(event)
})
return channel;
}
function createChannel() {
const messageQueue = []
const resolveQueue = []
function put(msg) {
// anyone waiting for a message ?
if (resolveQueue.length) {
// deliver the message to the oldest one waiting (First In First Out)
const nextResolve = resolveQueue.shift()
nextResolve(msg)
} else {
// no one is waiting ? queue the event
messageQueue.push(msg)
}
}
// returns a Promise resolved with the next message
function take() {
// do we have queued messages ?
if (messageQueue.length) {
// deliver the oldest queued message
return Promise.resolve(messageQueue.shift())
} else {
// no queued messages ? queue the taker until a message arrives
return new Promise((resolve) => resolveQueue.push(resolve))
}
}
return {
take,
put
}
}
Thanks for the help!

Get pending messages from a Chat

I am developing a chat using quickblox but I am having some problems when I open a new chat. Suddenly I received all the messages that others users sends to me when I was desconnected. The problem is that when I start a chat with user A, I receive the chats from users B, C, D.. in user A chat room.
I have find the way to only show the A users. But the problem is that the server has already sent to me the "disconnected" messages, so when I start a chat to B I do not receive any text because the message that the user B sent to me has been delivered (and ommitted) while I was chating with user A.
How can I do to receive the pending messages (kind of history) or to just retreive the message of the chat I am logged in?
A piece of my code:
// Create Connection.
Connection.DEBUG_ENABLED = true;
config = new ConnectionConfiguration(CHAT_SERVER);
connection = new XMPPConnection(config);
try {
connection.connect();
connection.login(chatLogin, password);
// Create Chat Manager.
chatManager = connection.getChatManager();
// Create Chat.
chat = chatManager.createChat(friendLogin, null);
// // Set listener for outcoming messages.
// chatManager.addChatListener(chatManagerListener);
// Accept only messages from
String from_messages = Integer.toString(receiver_chat_id);
PacketFilter filter = new AndFilter(new PacketTypeFilter(Message.class),
new FromContainsFilter(from_messages+"-3758#chat.quickblox.com"));
// Collect these messages
PacketCollector collector = connection.createPacketCollector(filter);
Packet packet = collector.pollResult();
PacketListener myListener = new PacketListener() {
public void processPacket(Packet packet) {
if (packet instanceof Message) {
Message msg = (Message) packet;
if(msg!=null){
// Process message
System.out.println("Rebem missatge: " +msg.getBody());
}
}
}
};
// Register the listener.
connection.addPacketListener(myListener, filter);
// Set listener for detect Receiver Status
if (connection.isConnected()){
roster = connection.getRoster();
roster.addRosterListener(new RosterListener() {
public void entriesDeleted(Collection<String> addresses) {}
public void entriesUpdated(Collection<String> addresses) {}
public void presenceChanged(Presence presence) {}
public void entriesAdded(Collection<String> arg0) {}
});
}
Make a arraylist and store the receiving offline messages into that array-list. you could add a code in your processPacket(Packet packet) function to add incoming messages to the array-list. or you could use Multimaps(Google Guava) to store all the incoming messages with the key. and when you open the activity that displays the messages from the certain person you could match the name of that person with the key(stored in multimap) and displays the message of that certain person. And the better option is to store all the incomming and outgoing message chat with the certain person so that you could show all the previous chat then you open up the activity.

cometd bayeux can't send message to a specific client

//StockPriceEmitter is a "dead loop" thread which generate data, and invoke StockPriceService.onUpdates() to send data.
#Service
public class StockPriceService implements StockPriceEmitter.Listener
{
#Inject
private BayeuxServer bayeuxServer;
#Session
private LocalSession sender;
public void onUpdates(List<StockPriceEmitter.Update> updates)
{
for (StockPriceEmitter.Update update : updates)
{
// Create the channel name using the stock symbol
String channelName = "/stock/" + update.getSymbol().toLowerCase(Locale.ENGLISH);
// Initialize the channel, making it persistent and lazy
bayeuxServer.createIfAbsent(channelName, new ConfigurableServerChannel.Initializer()
{
public void configureChannel(ConfigurableServerChannel channel)
{
channel.setPersistent(true);
channel.setLazy(true);
}
});
// Convert the Update business object to a CometD-friendly format
Map<String, Object> data = new HashMap<String, Object>(4);
data.put("symbol", update.getSymbol());
data.put("oldValue", update.getOldValue());
data.put("newValue", update.getNewValue());
// Publish to all subscribers
ServerChannel channel = bayeuxServer.getChannel(channelName);
channel.publish(sender, data, null); // this code works fine
//this.sender.getServerSession().deliver(sender, channel.getId(), data, null); // this code does not work
}
}
}
this line channel.publish(sender, data, null); // this code works fine works fine, now I don't want channel to publish message to all clients subscirbed with it, I want to send to a specific client, so I write this this.sender.getServerSession().deliver(sender, channel.getId(), data, null);, but it does not work, browser can't get message.
thx in advance.
I strongly recommend that you spend some time reading the CometD concepts page, in particular the section about sessions.
Your code does not work because you are sending the message to the sender, not to the recipient.
You need to pick which remote ServerSession you want to send the message to among the many that may be connected to your server, and call serverSession.deliver(...) on that remote ServerSession.
How to pick the remote ServerSession depends on your application.
For example:
for (ServerSession session : bayeuxServer.getSessions())
{
if (isAdminUser(session))
session.deliver(sender, channel.getId(), data, null);
}
You have to provide an implementation of isAdmin(ServerSession) with your logic, of course.
Note that you don't need to iterate over the sessions: if you happen to know the session id to deliver to, you can do:
bayeuxServer.getSession(sessionId).deliver(sender, channel.getId(), data, null);
Also refer to the CometD chat demo shipped with the CometD distribution, that contain a full fledged example of how to send a message to particular session.

android GCM Receive Messages from Multiple devices

i am building a chat application with the help of GoogleCloudMessaging(GCM).i am able to send and receive messages. my problem is when i receive messages from multiple devices at the same time, all those messages are appended to the same list-view in my broadcast receiver class. how can i separate the message based on the senders and append the current chat message to the listview. and make separate notifications for other messages based on the senders and when i click on the notification it should open the same list view with messages according to sender.
can any one give me an efficient way of doing this.if you have any sample code to handle this situation please post the code.
My current code:
public class Serious extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
// TODO Auto-generated method stub
String action=intent.getAction();
if (action.equals("com.google.android.c2dm.intent.REGISTRATION"))
{
String registrationID=intent.getStringExtra("registration_id");
// Log.i("uo",registrationID);
String error=intent.getStringExtra("error");
String unregisterd=intent.getStringExtra("unregistered");
}
else if(action.equals("com.google.android.c2dm.intent.RECEIVE"))
{
String data1=intent.getStringExtra("data1");
String data2=intent.getStringExtra("data2");
addNewMessage(new Message(data2, false));
/* PendingIntent contentIntent = PendingIntent.getActivity(context, 0,
new Intent(context, MainActivity.class), 0);
NotificationCompat.Builder mBuilder =
new NotificationCompat.Builder(context)
.setSmallIcon(R.drawable.ic_launcher)
.setContentTitle("My Notification")
.setDefaults(Notification.DEFAULT_SOUND)
.setAutoCancel(true)
.setContentText(data1+data2);
mBuilder.setContentIntent(contentIntent);
NotificationManager mNotificationManager =
(NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
mNotificationManager.notify(1, mBuilder.build());*/
}
}
void addNewMessage(Message m)
{
MainActivity.messages.add(m);
MainActivity.adapter.notifyDataSetChanged();
//MainActivity.getListView().setSelection(MainActivity.messages.size()-1);
}
}
You should pass in your gcm message a parameter that contains the sender id. Then, when you handle the arrived message, use that sender id to decide where to add that message. In order to show multiple notifications, pass different int values to notify. Currently you always pass 1, so a new notification overrides the old one.