The Magic Frog: Improve Bot Stability (Task Response)

in #utopian-io6 years ago (edited)

Repository

https://github.com/mktcode/the-magic-story-machine

Work Done

The work here was 2-fold.

  • Voting queue to force votes to be made in sequence and synchronously
  • Force vote after commentOptions to be synchronous to ensure best possible outcome

Voting Queue

It's just a list using push and shift to add details to a queue about how to vote and what to vote on. The queue is using first-in-last-out (FILO) to ensure votes are handled in order. Promises were used to avoid asynchronous collisions.

Forcing Vote after commentOptions

This isn't so much about forcing a vote as it is about ensuring the vote happens in a certain order. The request was originally sent after commentOptions which led to actions sometimes happening out of order. The queue is used in this case to prevent actions from happening out of order.

Details

diff --git a/helper.js b/helper.js
index e24aa52..84904e5 100644
--- a/helper.js
+++ b/helper.js
@@ -1,5 +1,20 @@
 const steem = require('steem');
 const locales = require('./locales');
+const EventEmitter = require('events')
+
+const voting_queue = [];
+const FIVE_SECONDS = 5000
+const TEN_MINUTES = 600000
+const THIRTY_MINUTES = 1800000
+
+const voting = {
+    length: () => { return voting_queue.length },
+    push: (obj) => { return voting_queue.push(obj) },
+    pop: () => { return voting_queue.pop() },
+    shift: () => { return voting_queue.shift() },
+    unshift: (obj) => { return voting_queue.unshift(obj) }
+}
+

Above is the actual structure for the voting queue.

 module.exports = {
   BOT_ACCOUNT_NAME: process.env.BOT_ACCOUNT_NAME,
@@ -232,35 +247,14 @@ module.exports = {
         });
 
         // vote
-        steem.broadcast.vote(this.BOT_KEY, this.BOT_ACCOUNT_NAME, this.BOT_ACCOUNT_NAME, permlink, 10000);
+        this.upvote({ author: this.BOT_ACCOUNT_NAME, permlink: permlink }, 10000)
       } else {
         console.log(err);
       }
     });
   },
   upvote(comment, weight) {
-    steem.api.getActiveVotes(comment.author, comment.permlink, (err, result) => {
-      if (err) {
-        console.log(err);
-      } else {
-        // check if already voted
-        let voted = false;
-        result.forEach((vote) => {
-          if (vote.voter === this.BOT_ACCOUNT_NAME && vote.percent > 0) {
-            voted = true;
-          }
-        });
-
-        // vote
-        if (!voted) {
-          steem.broadcast.vote(this.BOT_KEY, this.BOT_ACCOUNT_NAME, comment.author, comment.permlink, weight, (err) => {
-            if (err) {
-              console.log(err);
-            }
-          });
-        }
-      }
-    });
+    upvote_queue.push({ comment: comment, weight: weight, key: this.BOT_KEY, bot_account_name: this.BOT_ACCOUNT_NAME})
   },
   transfer(to, amount, memo) {
     steem.broadcast.transfer(this.BOT_KEY, this.BOT_ACCOUNT_NAME, to, amount.toFixed(3) + ' SBD', memo, function(err) {
@@ -269,4 +263,36 @@ module.exports = {
       }
     });
   }
-};

Above is replacing the existing function with a new function that appends the queue with memento data for voting.

+};
+
+setInterval(() => {
+  const options = voting_queue.pop()
+  if (options) {
+    real_upvote(options)
+        .catch((err) => {
+          // If there's an error, just push it back on the stack and retry it
+          // Really, we want to just do this if it's because it was inside
+          // the voting threshold. TODO: There should be a check to verify first
+          voting_queue.push(options)
+        })
+  }
+}, FIVE_SECONDS)
+
+function real_upvote(options) {
+  const {comment, weight, key, bot_account_name } = options
+  return steem.api.getActiveVotesAsync(comment.author, comment.permlink)
+    .filter((vote) => vote.voter === bot_account_name && vote.percent > 0)
+    .then((votes) => {
+      if (votes.length > 0) { // Already voted?
+        return votes
+      }
+
+      return steem.broadcast.voteAsync(key, bot_account_name, comment.author, comment.permlink, weight)
+          .then((results) => {
+            // Handle results
+          })
+          .catch((error) => {
+            // Handle voting error
+          })
+    })
+}

Above is the actual queue and voting implementation that shifts voting data off the front of the queue, then handles it.

Github

https://github.com/mktcode/the-magic-story-machine/pull/1

Sort:  

Thank you very much! Just one thing... you used the tag task-development but it should actually be just development. ;)

Oh and @emrebeyler said it's possible to post and set beneficiaries with one transaction. If you want, you can try to implement this too. Would be even better I guess.

Dang it! I guess I can change the development tag still. Also, now that I think about it steem.broadcast.send will allow extensions. We can give that a shot.

I revised the PR so that the comment, comment_options, and vote happen in a single transaction.

:kiss: I love you! :)

I commented a bit on the code in the PR. I have some questions. If you could have a second look at the PR, would be nice! :)

Nice Development!

  • The code looks good.
  • The project owner is happy with your work.
  • The code could use more comments.

Your contribution has been evaluated according to Utopian policies and guidelines, as well as a predefined set of questions pertaining to the category.

To view those questions and the relevant answers related to your post, click here.


Need help? Write a ticket on https://support.utopian.io/.
Chat with us on Discord.
[utopian-moderator]

Wow! That's weird that this came after the upvote. I'm not used to that. That upvote was so tasty. I'm assuming if I add more comments that's one way to get an even better upvote, so I'll definitely do that. I can't wait for v2

The voting bot is sometimes very fast. You’re welcome. And bon appétit! ;-)

Hey @r351574nc3
Thanks for contributing on Utopian.
We’re already looking forward to your next contribution!

Contributing on Utopian
Learn how to contribute on our website or by watching this tutorial on Youtube.

Want to chat? Join us on Discord https://discord.gg/h52nFrV.

Vote for Utopian Witness!

Woohoo! Thanks much!

Coin Marketplace

STEEM 0.17
TRX 0.13
JST 0.027
BTC 59099.74
ETH 2639.21
USDT 1.00
SBD 2.49