optimizing badger cache, won a 10-15% improvement in most benchmarks
This commit is contained in:
188
pkg/dgraph/subscriptions.go
Normal file
188
pkg/dgraph/subscriptions.go
Normal file
@@ -0,0 +1,188 @@
|
||||
package dgraph
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"next.orly.dev/pkg/database"
|
||||
"next.orly.dev/pkg/encoders/hex"
|
||||
)
|
||||
|
||||
// Subscription and payment methods
|
||||
// Simplified implementation using marker-based storage
|
||||
// For production, these should use proper graph nodes with relationships
|
||||
|
||||
// GetSubscription retrieves subscription information for a pubkey
|
||||
func (d *D) GetSubscription(pubkey []byte) (*database.Subscription, error) {
|
||||
key := "sub_" + hex.Enc(pubkey)
|
||||
data, err := d.GetMarker(key)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var sub database.Subscription
|
||||
if err := json.Unmarshal(data, &sub); err != nil {
|
||||
return nil, fmt.Errorf("failed to unmarshal subscription: %w", err)
|
||||
}
|
||||
|
||||
return &sub, nil
|
||||
}
|
||||
|
||||
// IsSubscriptionActive checks if a pubkey has an active subscription
|
||||
func (d *D) IsSubscriptionActive(pubkey []byte) (bool, error) {
|
||||
sub, err := d.GetSubscription(pubkey)
|
||||
if err != nil {
|
||||
return false, nil // No subscription = not active
|
||||
}
|
||||
|
||||
return sub.PaidUntil.After(time.Now()), nil
|
||||
}
|
||||
|
||||
// ExtendSubscription extends a subscription by the specified number of days
|
||||
func (d *D) ExtendSubscription(pubkey []byte, days int) error {
|
||||
key := "sub_" + hex.Enc(pubkey)
|
||||
|
||||
// Get existing subscription or create new
|
||||
var sub database.Subscription
|
||||
data, err := d.GetMarker(key)
|
||||
if err == nil {
|
||||
if err := json.Unmarshal(data, &sub); err != nil {
|
||||
return fmt.Errorf("failed to unmarshal subscription: %w", err)
|
||||
}
|
||||
} else {
|
||||
// New subscription - set trial period
|
||||
sub.TrialEnd = time.Now()
|
||||
sub.PaidUntil = time.Now()
|
||||
}
|
||||
|
||||
// Extend expiration
|
||||
if sub.PaidUntil.Before(time.Now()) {
|
||||
sub.PaidUntil = time.Now()
|
||||
}
|
||||
sub.PaidUntil = sub.PaidUntil.Add(time.Duration(days) * 24 * time.Hour)
|
||||
|
||||
// Save
|
||||
data, err = json.Marshal(sub)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to marshal subscription: %w", err)
|
||||
}
|
||||
|
||||
return d.SetMarker(key, data)
|
||||
}
|
||||
|
||||
// RecordPayment records a payment for subscription extension
|
||||
func (d *D) RecordPayment(
|
||||
pubkey []byte, amount int64, invoice, preimage string,
|
||||
) error {
|
||||
// Store payment in payments list
|
||||
key := "payments_" + hex.Enc(pubkey)
|
||||
|
||||
var payments []database.Payment
|
||||
data, err := d.GetMarker(key)
|
||||
if err == nil {
|
||||
if err := json.Unmarshal(data, &payments); err != nil {
|
||||
return fmt.Errorf("failed to unmarshal payments: %w", err)
|
||||
}
|
||||
}
|
||||
|
||||
payment := database.Payment{
|
||||
Amount: amount,
|
||||
Timestamp: time.Now(),
|
||||
Invoice: invoice,
|
||||
Preimage: preimage,
|
||||
}
|
||||
|
||||
payments = append(payments, payment)
|
||||
|
||||
data, err = json.Marshal(payments)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to marshal payments: %w", err)
|
||||
}
|
||||
|
||||
return d.SetMarker(key, data)
|
||||
}
|
||||
|
||||
// GetPaymentHistory retrieves payment history for a pubkey
|
||||
func (d *D) GetPaymentHistory(pubkey []byte) ([]database.Payment, error) {
|
||||
key := "payments_" + hex.Enc(pubkey)
|
||||
|
||||
data, err := d.GetMarker(key)
|
||||
if err != nil {
|
||||
return nil, nil // No payments = empty list
|
||||
}
|
||||
|
||||
var payments []database.Payment
|
||||
if err := json.Unmarshal(data, &payments); err != nil {
|
||||
return nil, fmt.Errorf("failed to unmarshal payments: %w", err)
|
||||
}
|
||||
|
||||
return payments, nil
|
||||
}
|
||||
|
||||
// ExtendBlossomSubscription extends a Blossom storage subscription
|
||||
func (d *D) ExtendBlossomSubscription(
|
||||
pubkey []byte, tier string, storageMB int64, daysExtended int,
|
||||
) error {
|
||||
key := "blossom_" + hex.Enc(pubkey)
|
||||
|
||||
// Simple implementation - just store tier and expiry
|
||||
data := map[string]interface{}{
|
||||
"tier": tier,
|
||||
"storageMB": storageMB,
|
||||
"extended": daysExtended,
|
||||
"updated": time.Now(),
|
||||
}
|
||||
|
||||
jsonData, err := json.Marshal(data)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to marshal blossom subscription: %w", err)
|
||||
}
|
||||
|
||||
return d.SetMarker(key, jsonData)
|
||||
}
|
||||
|
||||
// GetBlossomStorageQuota retrieves the storage quota for a pubkey
|
||||
func (d *D) GetBlossomStorageQuota(pubkey []byte) (quotaMB int64, err error) {
|
||||
key := "blossom_" + hex.Enc(pubkey)
|
||||
|
||||
data, err := d.GetMarker(key)
|
||||
if err != nil {
|
||||
return 0, nil // No subscription = 0 quota
|
||||
}
|
||||
|
||||
var result map[string]interface{}
|
||||
if err := json.Unmarshal(data, &result); err != nil {
|
||||
return 0, fmt.Errorf("failed to unmarshal blossom data: %w", err)
|
||||
}
|
||||
|
||||
// Default quota based on tier - simplified
|
||||
if tier, ok := result["tier"].(string); ok {
|
||||
switch tier {
|
||||
case "basic":
|
||||
return 100, nil
|
||||
case "premium":
|
||||
return 1000, nil
|
||||
default:
|
||||
return 10, nil
|
||||
}
|
||||
}
|
||||
|
||||
return 0, nil
|
||||
}
|
||||
|
||||
// IsFirstTimeUser checks if a pubkey is a first-time user
|
||||
func (d *D) IsFirstTimeUser(pubkey []byte) (bool, error) {
|
||||
// Check if they have any subscription or payment history
|
||||
sub, _ := d.GetSubscription(pubkey)
|
||||
if sub != nil {
|
||||
return false, nil
|
||||
}
|
||||
|
||||
payments, _ := d.GetPaymentHistory(pubkey)
|
||||
if len(payments) > 0 {
|
||||
return false, nil
|
||||
}
|
||||
|
||||
return true, nil
|
||||
}
|
||||
Reference in New Issue
Block a user