package main
import (
"context"
"encoding/json"
"fmt"
"io"
"net/http"
"os"
"time"
posthook "github.com/posthook/posthook-go"
)
var client, _ = posthook.NewClient(os.Getenv("POSTHOOK_API_KEY"))
var signatures, _ = posthook.NewSignatures(os.Getenv("POSTHOOK_SIGNING_KEY"))
// 1. Schedule
func onUserProfileUpdate(user User) {
client.Hooks.Schedule(context.Background(), &posthook.HookScheduleParams{
Path: "/webhooks/sync/salesforce",
PostIn: "5m",
Data: map[string]string{
"userId": user.ID,
"triggeredAt": time.Now().Format(time.RFC3339),
},
})
}
// 2. Handle
func handleSyncSalesforce(w http.ResponseWriter, r *http.Request) {
body, _ := io.ReadAll(r.Body)
delivery, err := signatures.ParseDelivery(body, r.Header)
if err != nil {
http.Error(w, "Invalid signature", http.StatusUnauthorized)
return
}
var data struct {
UserID string `json:"userId"`
TriggeredAt string `json:"triggeredAt"`
}
json.Unmarshal(delivery.Data, &data)
user, _ := db.GetUser(data.UserID)
// STALE CHECK:
// If the user record has been updated SINCE this hook was scheduled,
// then a newer hook exists in the queue. We can safely skip this one.
triggeredAt, _ := time.Parse(time.RFC3339, data.TriggeredAt)
if user.UpdatedAt.After(triggeredAt) {
fmt.Fprint(w, "Stale request, skipping")
return
}
// If timestamps match (or are very close), this is the latest action.
salesforce.Sync(user)
fmt.Fprint(w, "Synced")
}