From d5dd602c1db2c62d2754a3ab71d82decbc5c7b1d Mon Sep 17 00:00:00 2001
From: mtrela <mtrela@syncad.com>
Date: Tue, 28 Jul 2020 15:27:13 +0200
Subject: [PATCH] Votes inserted by `vote_operation` and updated by
 `effective_comment_vote_operation` operation

---
 hive/indexer/blocks.py |   3 +-
 hive/indexer/posts.py  |  11 +++--
 hive/indexer/votes.py  | 108 ++++++++++++++++++++++++++++++++++-------
 3 files changed, 99 insertions(+), 23 deletions(-)

diff --git a/hive/indexer/blocks.py b/hive/indexer/blocks.py
index a8ed93683..4c049d0c9 100644
--- a/hive/indexer/blocks.py
+++ b/hive/indexer/blocks.py
@@ -229,6 +229,7 @@ class Blocks:
                     if not is_initial_sync:
                         Accounts.dirty(op['author']) # lite - rep
                         Accounts.dirty(op['voter']) # lite - stats
+                    Votes.vote_op(op)
 
                 # misc ops
                 elif op_type == 'transfer_operation':
@@ -254,7 +255,7 @@ class Blocks:
             (vote_ops, comment_payout_ops) = Blocks.prepare_vops(vops, cls._head_block_date)
 
         for k, v in vote_ops.items():
-            Votes.vote_op(v, cls._head_block_date)
+            Votes.effective_comment_vote_op(v, cls._head_block_date)
             op_type = 'effective_comment_vote_operation'
             if op_type in cls.ops_stats:
                 cls.ops_stats[op_type] += 1
diff --git a/hive/indexer/posts.py b/hive/indexer/posts.py
index e60cc40be..d3184e3e2 100644
--- a/hive/indexer/posts.py
+++ b/hive/indexer/posts.py
@@ -287,13 +287,14 @@ class Posts:
               pending_payout = 0
 
             #Calculations of all dates
-            if ( total_payout_value is not None ):
-              payout_at = date
-              last_payout = date
-
             if ( is_paidout is not None ):
               payout_at = date
-              cashout_time = date
+              last_payout = date
+              cashout_time = "1969-12-31T23:59:59"
+            else:
+              if ( total_payout_value is not None ):
+                payout_at = date  #Here should be `cashout_time`
+                last_payout = date
 
             values.append("('{}', '{}', {}, {}, {}, {}, {}, {}, {}, {}, {}, '{}'::timestamp, {}, {}, {})".format(
               author,
diff --git a/hive/indexer/votes.py b/hive/indexer/votes.py
index b5ce7cfdd..e5e47947f 100644
--- a/hive/indexer/votes.py
+++ b/hive/indexer/votes.py
@@ -10,6 +10,7 @@ DB = Db.instance()
 class Votes:
     """ Class for managing posts votes """
     _votes_data = {}
+    _effective_votes_data = {}
 
     @classmethod
     def get_vote_count(cls, author, permlink):
@@ -64,34 +65,51 @@ class Votes:
         cls._votes_data[key] = dict(voter=voter,
                                     author=author,
                                     permlink=permlink,
-                                    vote_percent=vop['vote_percent'],
-                                    weight=vop['weight'],
-                                    rshares=vop['rshares'],
-                                    last_update=date)
+                                    weight=vop['weight'])
 
     @classmethod
-    def flush(cls):
+    def effective_comment_vote_op(cls, vop, date):
+        """ Process effective_comment_vote_operation """
+        voter = vop['voter']
+        author = vop['author']
+        permlink = vop['permlink']
+
+        if(cls.inside_flush):
+            log.info("Adding new effective comment vote into '_effective_votes_data' dict")
+            raise "Fatal error"
+
+        key = voter + "/" + author + "/" + permlink
+
+        cls._effective_votes_data[key] = dict(voter=voter,
+                                              author=author,
+                                              permlink=permlink,
+                                              vote_percent=vop['vote_percent'],
+                                              weight=vop['weight'],
+                                              rshares=vop['rshares'],
+                                              last_update=date)
+
+    @classmethod
+    def flush_votes(cls):
         """ Flush vote data from cache to database """
-        cls.inside_flush = True
         if cls._votes_data:
             sql = """
                     INSERT INTO hive_votes
-                    (post_id, voter_id, author_id, permlink_id, weight, rshares, vote_percent, last_update) 
-                    select data_source.post_id, data_source.voter_id, data_source.author_id, data_source.permlink_id, data_source.weight, data_source.rshares, data_source.vote_percent, data_source.last_update
-                    from 
+                    (post_id, voter_id, author_id, permlink_id, weight) 
+                    select data_source.post_id, data_source.voter_id, data_source.author_id, data_source.permlink_id, data_source.weight
+                    from
                     (
-                    SELECT hp.id as post_id, ha_v.id as voter_id, ha_a.id as author_id, hpd_p.id as permlink_id, t.weight, t.rshares, t.vote_percent, t.last_update
+                    SELECT hp.id as post_id, ha_v.id as voter_id, ha_a.id as author_id, hpd_p.id as permlink_id, t.weight
                     from
                     (
                     VALUES
-                    --   voter, author, permlink, weight, rshares, vote_percent, last_update
+                    --   voter, author, permlink, weight
                       {}
-                    ) AS T(voter, author, permlink, weight, rshares, vote_percent, last_update)
+                    ) AS T(voter, author, permlink, weight)
                     INNER JOIN hive_accounts ha_v ON ha_v.name = t.voter
                     INNER JOIN hive_accounts ha_a ON ha_a.name = t.author
                     INNER JOIN hive_permlink_data hpd_p ON hpd_p.permlink = t.permlink
-                    INNER JOIN hive_posts hp ON hp.author_id = ha_a.id AND hp.permlink_id = hpd_p.id
-                    ) as data_source(post_id, voter_id, author_id, permlink_id, weight, rshares, vote_percent, last_update)
+                    INNER JOIN hive_posts hp ON hp.author_id = ha_a.id AND hp.permlink_id = hpd_p.id  
+                    ) as data_source(post_id, voter_id, author_id, permlink_id, weight)
                     ON CONFLICT ON CONSTRAINT hive_votes_ux1 DO
                       UPDATE
                         SET
@@ -107,8 +125,8 @@ class Votes:
             values_limit = 1000
 
             for _, vd in cls._votes_data.items():
-                values.append("('{}', '{}', '{}', {}, {}, {}, '{}'::timestamp)".format(
-                    vd['voter'], vd['author'], vd['permlink'], vd['weight'], vd['rshares'], vd['vote_percent'], vd['last_update']))
+                values.append("('{}', '{}', '{}', {})".format(
+                    vd['voter'], vd['author'], vd['permlink'], vd['weight']))
 
                 if len(values) >= values_limit:
                     values_str = ','.join(values)
@@ -123,4 +141,60 @@ class Votes:
                 values.clear()
 
             cls._votes_data.clear()
-        cls.inside_flush = False
+
+    @classmethod
+    def flush_effective_votes(cls):
+        """ Flush vote data from cache to database """
+        if cls._effective_votes_data:
+          sql = """
+                UPDATE hive_votes AS hv SET
+                  weight        = data_source.weight,
+                  rshares       = data_source.rshares,
+                  vote_percent  = data_source.vote_percent,
+                  last_update   = data_source.last_update,
+                  num_changes   = hv.num_changes + 1
+                FROM
+                  (
+                  SELECT ha_v.id as voter_id, ha_a.id as author_id, hpd_p.id as permlink_id, t.weight, t.rshares, t.vote_percent, t.last_update
+                  FROM
+                  (
+                  VALUES
+                  --   voter, author, permlink, weight, rshares, vote_percent, last_update
+                    {}
+                  ) AS T(voter, author, permlink, weight, rshares, vote_percent, last_update)
+                  INNER JOIN hive_accounts ha_v ON ha_v.name = t.voter
+                  INNER JOIN hive_accounts ha_a ON ha_a.name = t.author
+                  INNER JOIN hive_permlink_data hpd_p ON hpd_p.permlink = t.permlink
+                  ) as data_source(voter_id, author_id, permlink_id, weight, rshares, vote_percent, last_update)
+                  WHERE hv.voter_id = data_source.voter_id and hv.author_id = data_source.author_id and hv.permlink_id = data_source.permlink_id;
+                """
+
+          values = []
+          values_limit = 1000
+
+          for _, vd in cls._effective_votes_data.items():
+              values.append("('{}', '{}', '{}', {}, {}, {}, '{}'::timestamp)".format(
+                  vd['voter'], vd['author'], vd['permlink'], vd['weight'], vd['rshares'], vd['vote_percent'], vd['last_update']))
+
+              if len(values) >= values_limit:
+                  values_str = ','.join(values)
+                  actual_query = sql.format(values_str)
+                  DB.query(actual_query)
+                  values.clear()
+
+          if len(values) > 0:
+              values_str = ','.join(values)
+              actual_query = sql.format(values_str)
+              DB.query(actual_query)
+              values.clear()
+
+          cls._effective_votes_data.clear()
+
+    @classmethod
+    def flush(cls):
+      cls.inside_flush = True
+
+      cls.flush_votes()
+      cls.flush_effective_votes()
+
+      cls.inside_flush = False
\ No newline at end of file
-- 
GitLab