Skip to content
This repository has been archived by the owner on Jan 13, 2021. It is now read-only.

Commit

Permalink
make sure to calculate deduplicated storage update
Browse files Browse the repository at this point in the history
  • Loading branch information
postables committed Apr 18, 2020
1 parent 25376ab commit 9145b52
Show file tree
Hide file tree
Showing 5 changed files with 18 additions and 29 deletions.
2 changes: 1 addition & 1 deletion api/v2/routes_frontend.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ func (api *API) calculatePinCost(c *gin.Context) {
return
}
// calculate pin cost
totalCost, err := utils.CalculatePinCost(username, hash, holdTimeInt, api.ipfs, api.usage)
totalCost, _, err := utils.CalculatePinCost(username, hash, holdTimeInt, api.ipfs, api.usage)
if err != nil {
api.LogError(c, err, eh.CostCalculationError)(http.StatusBadRequest)
Fail(c, err)
Expand Down
14 changes: 4 additions & 10 deletions api/v2/routes_ipns.go
Original file line number Diff line number Diff line change
Expand Up @@ -167,14 +167,8 @@ func (api *API) pinIPNSHash(c *gin.Context) {
Respond(c, http.StatusBadRequest, gin.H{"response": alreadyUploadedMessage})
return
}
// get size of object
stats, err := api.ipfs.Stat(hash)
if err != nil {
api.LogError(c, err, eh.IPFSObjectStatError)(http.StatusBadRequest)
return
}
// get the cost of this object
cost, err := utils.CalculatePinCost(username, hash, holdTimeInt, api.ipfs, api.usage)
cost, size, err := utils.CalculatePinCost(username, hash, holdTimeInt, api.ipfs, api.usage)
if err != nil {
api.LogError(c, err, eh.CostCalculationError)(http.StatusBadRequest)
return
Expand All @@ -184,7 +178,7 @@ func (api *API) pinIPNSHash(c *gin.Context) {
api.LogError(c, err, eh.InvalidBalanceError)(http.StatusPaymentRequired)
return
}
if err := api.usage.UpdateDataUsage(username, uint64(stats.CumulativeSize)); err != nil {
if err := api.usage.UpdateDataUsage(username, uint64(size)); err != nil {
api.LogError(c, err, eh.CantUploadError)(http.StatusBadRequest)
api.refundUserCredits(username, "pin", cost)
return
Expand All @@ -196,13 +190,13 @@ func (api *API) pinIPNSHash(c *gin.Context) {
UserName: username,
HoldTimeInMonths: holdTimeInt,
CreditCost: cost,
Size: int64(stats.CumulativeSize),
Size: int64(size),
}
// send message for processing
if err = api.queues.cluster.PublishMessage(qp); err != nil {
api.LogError(c, err, eh.QueuePublishError)(http.StatusBadRequest)
api.refundUserCredits(username, "pin", cost)
api.usage.ReduceDataUsage(username, uint64(stats.CumulativeSize))
api.usage.ReduceDataUsage(username, uint64(size))
return
}
// log and return
Expand Down
16 changes: 5 additions & 11 deletions api/v2/routes_rtfs.go
Original file line number Diff line number Diff line change
Expand Up @@ -54,14 +54,8 @@ func (api *API) pinHashLocally(c *gin.Context) {
Respond(c, http.StatusBadRequest, gin.H{"response": alreadyUploadedMessage})
return
}
// get object size
stats, err := api.ipfs.Stat(hash)
if err != nil {
api.LogError(c, err, eh.IPFSObjectStatError)(http.StatusBadRequest)
return
}
// determine cost of upload
cost, err := utils.CalculatePinCost(username, hash, holdTimeInt, api.ipfs, api.usage)
cost, size, err := utils.CalculatePinCost(username, hash, holdTimeInt, api.ipfs, api.usage)
if err != nil {
api.LogError(c, err, eh.CostCalculationError)(http.StatusBadRequest)
return
Expand All @@ -72,7 +66,7 @@ func (api *API) pinHashLocally(c *gin.Context) {
return
}
// update their data usage
if err := api.usage.UpdateDataUsage(username, uint64(stats.CumulativeSize)); err != nil {
if err := api.usage.UpdateDataUsage(username, uint64(size)); err != nil {
api.LogError(c, err, eh.CantUploadError)(http.StatusBadRequest)
api.refundUserCredits(username, "pin", cost)
return
Expand All @@ -83,15 +77,15 @@ func (api *API) pinHashLocally(c *gin.Context) {
NetworkName: "public",
UserName: username,
HoldTimeInMonths: holdTimeInt,
Size: int64(stats.CumulativeSize),
Size: size,
CreditCost: cost,
FileName: c.PostForm("file_name"),
}
// sent pin message
if err = api.queues.cluster.PublishMessage(qp); err != nil {
api.LogError(c, err, eh.QueuePublishError)(http.StatusBadRequest)
api.refundUserCredits(username, "pin", cost)
api.usage.ReduceDataUsage(username, uint64(stats.CumulativeSize))
api.usage.ReduceDataUsage(username, uint64(size))
return
}
// log success and return
Expand Down Expand Up @@ -381,7 +375,7 @@ func (api *API) extendPin(c *gin.Context) {
return
}
// calculate cost of hold time extension
cost, err := utils.CalculatePinCost(username, hash, holdTimeInt, api.ipfs, api.usage)
cost, _, err := utils.CalculatePinCost(username, hash, holdTimeInt, api.ipfs, api.usage)
if err != nil {
api.LogError(c, err, eh.CostCalculationError)(http.StatusBadRequest)
return
Expand Down
13 changes: 7 additions & 6 deletions utils/utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,20 +9,21 @@ import (
)

// CalculatePinCost is used to calculate the cost of pining a particular content hash
func CalculatePinCost(username, contentHash string, holdTimeInMonths int64, im rtfs.Manager, um *models.UsageManager) (float64, error) {
// it returns the cost to bill the user, as well as the calculated size of the pin
func CalculatePinCost(username, contentHash string, holdTimeInMonths int64, im rtfs.Manager, um *models.UsageManager) (float64, int64, error) {
// get total size of content hash in bytes ensuring that we calculate size
// by following unique references
sizeInBytes, _, err := rtfs.DedupAndCalculatePinSize(contentHash, im)
if err != nil {
return 0, err
return 0, 0, err
}
// if this is true, fall back to default calculation
// as it wont always be possible to calculate deduplicated
// storage costs if the object is not of a unixfs type
if sizeInBytes <= 0 {
stats, err := im.Stat(contentHash)
if err != nil {
return 0, err
return 0, 0, err
}
sizeInBytes = int64(stats.CumulativeSize)
}
Expand All @@ -37,15 +38,15 @@ func CalculatePinCost(username, contentHash string, holdTimeInMonths int64, im r
// get the users usage model
usage, err := um.FindByUserName(username)
if err != nil {
return 0, err
return 0, 0, err
}
// if they are free tier, they don't incur data charges
if usage.Tier == models.Free || usage.Tier == models.WhiteLabeled || usage.Tier == models.Unverified {
return 0, nil
return 0, sizeInBytes, nil
}
// dynamic pricing based on their usage tier
costPerMonthFloat := objectSizeInGigabytesFloat * usage.Tier.PricePerGB()
return costPerMonthFloat * float64(holdTimeInMonths), nil
return costPerMonthFloat * float64(holdTimeInMonths), sizeInBytes, nil
}

// CalculateFileCost is used to calculate the cost of storing a file
Expand Down
2 changes: 1 addition & 1 deletion utils/utils_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ func TestUtils_CalculatePinCost(t *testing.T) {
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
if _, err := utils.CalculatePinCost(
if _, _, err := utils.CalculatePinCost(
tt.args.username,
tt.args.hash,
tt.args.months,
Expand Down

0 comments on commit 9145b52

Please sign in to comment.