Returning delay until next report

This commit is contained in:
jstuczyn 2020-10-29 16:31:12 +00:00
parent 2f3ff63eb7
commit a971d27fd3
7 changed files with 139 additions and 13 deletions

View File

@ -1,5 +1,6 @@
// GENERATED BY THE COMMAND ABOVE; DO NOT EDIT
// This file was generated by swaggo/swag
// This file was generated by swaggo/swag at
// 2020-10-28 15:44:19.4192076 +0000 GMT m=+0.057120601
package docs
@ -117,7 +118,12 @@ var doc = `{
}
],
"responses": {
"201": {},
"201": {
"description": "Created",
"schema": {
"$ref": "#/definitions/models.MixMetricInterval"
}
},
"400": {
"description": "Bad Request",
"schema": {
@ -170,6 +176,14 @@ var doc = `{
}
}
}
},
"models.MixMetricInterval": {
"type": "object",
"properties": {
"nextReportIn": {
"type": "integer"
}
}
}
}
}`

View File

@ -100,7 +100,12 @@
}
],
"responses": {
"201": {},
"201": {
"description": "Created",
"schema": {
"$ref": "#/definitions/models.MixMetricInterval"
}
},
"400": {
"description": "Bad Request",
"schema": {
@ -153,6 +158,14 @@
}
}
}
},
"models.MixMetricInterval": {
"type": "object",
"properties": {
"nextReportIn": {
"type": "integer"
}
}
}
}
}

View File

@ -19,9 +19,16 @@ definitions:
- received
- sent
type: object
models.MixMetricInterval:
properties:
nextReportIn:
type: integer
type: object
info:
contact: {}
description: This is a temporarily centralized directory/PKI/metrics API to allow us to get the other Nym node types running. Its functionality will eventually be folded into other parts of Nym.
description: This is a temporarily centralized directory/PKI/metrics API to allow
us to get the other Nym node types running. Its functionality will eventually
be folded into other parts of Nym.
license:
name: Apache 2.0
url: https://github.com/nymtech/nym-directory/license
@ -33,7 +40,8 @@ paths:
get:
consumes:
- application/json
description: Returns a 200 if the directory server is available. Good route to use for automated monitoring.
description: Returns a 200 if the directory server is available. Good route
to use for automated monitoring.
operationId: healthCheck
produces:
- application/json
@ -46,7 +54,8 @@ paths:
get:
consumes:
- application/json
description: For demo and debug purposes it gives us the ability to generate useful visualisations of network traffic.
description: For demo and debug purposes it gives us the ability to generate
useful visualisations of network traffic.
operationId: listMixMetrics
produces:
- application/json
@ -75,7 +84,8 @@ paths:
post:
consumes:
- application/json
description: For demo and debug purposes it gives us the ability to generate useful visualisations of network traffic.
description: For demo and debug purposes it gives us the ability to generate
useful visualisations of network traffic.
operationId: createMixMetric
parameters:
- description: object
@ -87,7 +97,10 @@ paths:
produces:
- application/json
responses:
"201": {}
"201":
description: Created
schema:
$ref: '#/definitions/models.MixMetricInterval'
"400":
description: Bad Request
schema:
@ -100,7 +113,8 @@ paths:
description: Internal Server Error
schema:
$ref: '#/definitions/models.Error'
summary: Create a metric detailing how many messages a given mixnode sent and received
summary: Create a metric detailing how many messages a given mixnode sent and
received
tags:
- metrics
swagger: "2.0"

11
main.go
View File

@ -1,8 +1,11 @@
package main
import (
"fmt"
_ "github.com/nymtech/nym-directory/docs"
"github.com/nymtech/nym-directory/metrics"
"github.com/nymtech/nym-directory/server"
"os"
)
// @title Nym Directory API
@ -13,6 +16,14 @@ import (
// @license.name Apache 2.0
// @license.url https://github.com/nymtech/nym-directory/license
func main() {
args := os.Args[1:]
if len(args) != 1 {
fmt.Fprint(os.Stderr, "Expected single argument to be passed - address of the validator server")
return
}
validatorAddress := args[0]
router := server.New()
go metrics.DynamicallyUpdateReportDelay(validatorAddress)
router.Run(":8080")
}

View File

@ -1,7 +1,13 @@
package metrics
import (
"encoding/json"
"fmt"
"io/ioutil"
"net/http"
"os"
"sync/atomic"
"time"
"github.com/gin-gonic/gin"
"github.com/nymtech/nym-directory/models"
@ -19,6 +25,62 @@ type controller struct {
sanitizer Sanitizer
}
const MaxDesiredRequests = 50 // per second
const MinReportDelay uint64 = 5 // seconds
var nextReportDelay = MinReportDelay
// we don't care about structure itself, we just want to know the count
type Topology struct {
Gateways []interface{} `json:"gateways"`
MixNodes []interface{} `json:"mixNodes"`
}
func nodesCount(validatorAddress string) int64 {
resp, err := http.Get(validatorAddress + "/api/mixmining/topology")
if err != nil {
_, _ = fmt.Fprintf(os.Stderr, "failed to obtain network topology - %v", err)
return - 1
}
defer resp.Body.Close()
body, err := ioutil.ReadAll(resp.Body)
if err != nil {
_, _ = fmt.Fprintf(os.Stderr, "failed to obtain network topology - %v", err)
return -1
}
var topology Topology
err = json.Unmarshal(body, &topology)
if err != nil {
_, _ = fmt.Fprintf(os.Stderr, "failed to obtain network topology - %v", err)
return - 1
}
return int64(len(topology.MixNodes))
}
func DynamicallyUpdateReportDelay(validatorAddress string) {
updateTicker := time.NewTicker(time.Minute)
for {
<-updateTicker.C
onlineNodes := nodesCount(validatorAddress)
if onlineNodes > 0 {
newNextReportDelay := uint64(onlineNodes / MaxDesiredRequests)
if newNextReportDelay < MinReportDelay {
// no point in sending it SO often
newNextReportDelay = MinReportDelay
}
atomic.StoreUint64(&nextReportDelay, newNextReportDelay)
}
}
}
// Controller ...
type Controller interface {
CreateMixMetric(c *gin.Context)
@ -43,7 +105,7 @@ func (controller *controller) RegisterRoutes(router *gin.Engine) {
// @Produce json
// @Tags metrics
// @Param object body models.MixMetric true "object"
// @Success 201
// @Success 201 {object} models.MixMetricInterval
// @Failure 400 {object} models.Error
// @Failure 404 {object} models.Error
// @Failure 500 {object} models.Error
@ -56,7 +118,14 @@ func (controller *controller) CreateMixMetric(c *gin.Context) {
}
sanitized := controller.sanitizer.Sanitize(metric)
controller.service.CreateMixMetric(sanitized)
c.JSON(http.StatusCreated, gin.H{"ok": true})
nextReportDelay := atomic.LoadUint64(&nextReportDelay)
interval := models.MixMetricInterval{
NextReportIn: nextReportDelay,
}
c.JSON(http.StatusCreated, interval)
}
// ListMixMetrics lists mixnode activity

View File

@ -15,3 +15,8 @@ type PersistedMixMetric struct {
MixMetric
Timestamp int64 `json:"timestamp" binding:"required"`
}
// MixMetricInterval specifies when given node should submit its next report
type MixMetricInterval struct {
NextReportIn uint64 `json:"nextReportIn"`
}

View File

@ -1,14 +1,13 @@
package server
import (
"net/http"
"github.com/gin-gonic/gin"
"github.com/microcosm-cc/bluemonday"
"github.com/nymtech/nym-directory/healthcheck"
"github.com/nymtech/nym-directory/metrics"
"github.com/nymtech/nym-directory/server/html"
"github.com/nymtech/nym-directory/server/websocket"
"net/http"
"github.com/gin-contrib/cors"
swaggerFiles "github.com/swaggo/files"
@ -68,3 +67,4 @@ func injectMetrics(hub *websocket.Hub, policy *bluemonday.Policy) metrics.Config
Sanitizer: sanitizer,
}
}