def calculate(height, avg_range): avg_over_first_grin_block = Blocks.get_by_height( max(height-avg_range, 1) ) assert avg_over_first_grin_block is not None, "Missing grin block: {}".format(max(height-avg_range, 1)) grin_block = Blocks.get_by_height(height) assert grin_block is not None, "Missing grin block: {}".format(height) # Get all workers share records for the current range of blocks latest_worker_shares = Worker_shares.get_by_height(height) # assert len(latest_worker_shares) != 0, "Missing worker shares record for height {}".format(height) avg_over_worker_shares = Worker_shares.get_by_height(height, avg_range) # Create a worker_stats for each user who submitted a share in this range workers = list(set([share.worker for share in latest_worker_shares])) new_stats = [] for worker in workers: # Get this workers most recent worker_stats record (for running totals) last_stat = Worker_stats.get_latest_by_id(worker) if last_stat is None: # A new worker last_stat = Worker_stats(None, datetime.utcnow(), height-1, worker, 0, 0, 0, 0, 0, 0) new_stats.append(last_stat) # Calculate this workers stats data timestamp = grin_block.timestamp difficulty = POOL_MIN_DIFF # XXX TODO - enchance to support multiple difficulties num_shares_in_range = sum([shares.valid for shares in avg_over_worker_shares if shares.worker == worker]) gps = grin.calculate_graph_rate(difficulty, avg_over_first_grin_block.timestamp, grin_block.timestamp, num_shares_in_range) num_valid_this_block = [shares.valid for shares in latest_worker_shares if shares.worker == worker][0] num_invalid_this_block = [shares.invalid for shares in latest_worker_shares if shares.worker == worker][0] shares_processed = num_valid_this_block + num_invalid_this_block # latest_worker_shares = [share for share in latest_pool_shares if share.found_by == worker] #shares_processed = len(worker_shares_this_block) total_shares_processed = last_stat.total_shares_processed + shares_processed stats = Worker_stats( id = None, height = height, timestamp = timestamp, worker = worker, gps = gps, shares_processed = shares_processed, total_shares_processed = total_shares_processed, grin_paid = 123, # XXX TODO total_grin_paid = 456, # XXX TODO balance = 1) # XXX TODO new_stats.append(stats) return new_stats
def get(self, id, height=0, range=None, fields=None): global database #database = lib.get_db() LOGGER = lib.get_logger(PROCESS) # AUTH FILTER if id != g.user.id: response = jsonify( {'message': 'Not authorized to access data for other users'}) response.status_code = 403 return response debug and LOGGER.warn( "WorkerAPI_stats get id:{} height:{} range:{} fields:{}".format( id, height, range, fields)) # Enforce range limit if range is not None: range = min(range, worker_stats_range_limit) fields = lib.fields_to_list(fields) res = None if range is None: # Getting a single record if height == 0: # Get the most recent stats for this user res = Worker_stats.get_latest_by_id(id) else: res = Worker_stats.get_by_height_and_id(id, height) if res is None: return None return res.to_json(fields) else: # Getting a range of records if height == 0: height = Blocks.get_latest().height res = Worker_stats.get_by_height_and_id(id, height, range) if res is None: return None stats = [] for stat in res: stats.append(stat.to_json(fields)) return stats
def calculate(height, window_size): database = lib.get_db() grin_block = Blocks.get_by_height(height) assert grin_block is not None, "Missing grin block at height: {}".format(height) # Get all Worker_share records in the estimation window window = Worker_shares.get_by_height(height, window_size) # Get list of all workers who submitted shares OR recvd a payment at this height pmts = Pool_payment.get_by_height(height) shares_workers = [share.user_id for share in window] pmts_workers = [pmt.user_id for pmt in pmts] workers = list(set(shares_workers + pmts_workers)) # Create a new Worker_stats record for each of these workers print("Calcualte worker stats for height {}, workers {}".format(height, workers)) new_stats = [] for worker in workers: # Get this workers most recent worker_stats record (for running totals) last_stat = Worker_stats.get_latest_by_id(worker) if last_stat is None: # A new worker, initialize a last_stat for the previous block last_stat = Worker_stats( timestamp=datetime.utcnow(), height=height-1, user_id=worker) new_stats.append(last_stat) # Calculate this workers stats data timestamp = grin_block.timestamp # Caclulate estimated GPS for all sizes with shares submitted all_gps = estimate_gps_for_all_sizes(worker, window) # Keep track of share totals - sum counts of all share sizes submitted for this block print("Looking up shares for height {} user {}".format(height, worker)) this_workers_shares_this_block = Worker_shares.get_by_height_and_id(height, worker) print("XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX {}".format(this_workers_shares_this_block)) if this_workers_shares_this_block is None or len(this_workers_shares_this_block) == 0: this_workers_valid_shares = 0 this_workers_invalid_shares = 0 this_workers_stale_shares = 0 else: this_workers_shares_this_block = this_workers_shares_this_block[-1] this_workers_valid_shares = this_workers_shares_this_block.num_valid() this_workers_invalid_shares = this_workers_shares_this_block.num_invalid() this_workers_stale_shares = this_workers_shares_this_block.num_stale() this_workers_total_valid_shares = last_stat.total_valid_shares + this_workers_valid_shares this_workers_total_invalid_shares = last_stat.total_invalid_shares + this_workers_invalid_shares this_workers_total_stale_shares = last_stat.total_stale_shares + this_workers_stale_shares # XXX PERFORAMCE = removed bulk insert to debug some other issue, need to put bulk insert back!!! stats = Worker_stats( height = height, timestamp = timestamp, user_id = worker, valid_shares = this_workers_valid_shares, invalid_shares = this_workers_invalid_shares, stale_shares = this_workers_stale_shares, total_valid_shares = this_workers_total_valid_shares, total_invalid_shares = this_workers_total_invalid_shares, total_stale_shares = this_workers_total_stale_shares, ) database.db.getSession().add(stats) database.db.getSession().commit() #print("AAA: Created Worker_stats with id={}".format(stats.id)) # print("all_gps for worker {}:".format(worker)) # pp.pprint(all_gps) for gps_est in all_gps: gps_rec = Gps( edge_bits = gps_est[0], gps = gps_est[1], ) stats.gps.append(gps_rec) #print("AAA: Appended gps record to Worker_stats: {}".format(gps_rec)) # gps_rec.worker_stats_id = stats.id, # database.db.getSession().add(gps_rec) new_stats.append(stats) database.db.getSession().add(stats) database.db.getSession().commit() sys.stdout.flush() return new_stats
def calculate(height, window_size): database = lib.get_db() grin_block = Blocks.get_by_height(height) assert grin_block is not None, "Missing grin block at height: {}".format( height) # Get all Worker_share records in the estimation window window = Worker_shares.get_by_height(height, window_size) # Get list of all workers who submitted shares in the window workers = list(set([share.worker for share in window])) # Create a new Worker_stats record for each of these workers print("Calcualte worker stats for height {}, workers {}".format( height, workers)) new_stats = [] for worker in workers: # Get this workers most recent worker_stats record (for running totals) last_stat = Worker_stats.get_latest_by_id(worker) if last_stat is None: # A new worker, initialize a last_stat for the previous block last_stat = Worker_stats(None, datetime.utcnow(), height - 1, worker, 0, 0, 0, 0, 0, 0) new_stats.append(last_stat) # Calculate this workers stats data timestamp = grin_block.timestamp # Caclulate estimated GPS for all sizes with shares submitted all_gps = estimate_gps_for_all_sizes(worker, window) # Keep track of share totals - sum counts of all share sizes submitted for this block this_workers_shares = [ws for ws in window if ws.worker == worker] num_shares_processed = this_workers_shares[-1].num_shares() print("num_shares_processed={}".format(num_shares_processed)) total_shares_processed = last_stat.total_shares_processed + num_shares_processed print("total_shares_processed={}".format(total_shares_processed)) # XXX PERFORAMCE = could not get bulk_insert to work... stats = Worker_stats( id=None, height=height, timestamp=timestamp, worker=worker, shares_processed=num_shares_processed, total_shares_processed=total_shares_processed, grin_paid=123, # XXX TODO total_grin_paid=456, # XXX TODO balance=1) # XXX TODO database.db.getSession().add(stats) database.db.getSession().commit() #print("AAA: Created Worker_stats with id={}".format(stats.id)) # print("all_gps for worker {}:".format(worker)) # pp.pprint(all_gps) for gps_est in all_gps: gps_rec = Gps( edge_bits=gps_est[0], gps=gps_est[1], ) stats.gps.append(gps_rec) #print("AAA: Appended gps record to Worker_stats: {}".format(gps_rec)) # gps_rec.worker_stats_id = stats.id, # database.db.getSession().add(gps_rec) # new_stats.append(stats) database.db.getSession().add(stats) database.db.getSession().commit() sys.stdout.flush() return new_stats