forked from adserver-online/prebid-server
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathejector.go
More file actions
127 lines (107 loc) · 3.91 KB
/
Copy pathejector.go
File metadata and controls
127 lines (107 loc) · 3.91 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
package usersync
import (
"errors"
"time"
)
type Ejector interface {
Choose(uids map[string]UIDEntry) (string, error)
}
type OldestEjector struct{}
type PriorityBidderEjector struct {
PriorityGroups [][]string
SyncersByBidder map[string]Syncer
IsSyncerPriority bool
TieEjector Ejector
}
// Choose method for oldest ejector will return the oldest uid
func (o *OldestEjector) Choose(uids map[string]UIDEntry) (string, error) {
var oldestElement string
var oldestDate time.Time = time.Unix(1<<63-62135596801, 999999999) // Max value for time
for key, value := range uids {
if value.Expires.Before(oldestDate) {
oldestElement = key
oldestDate = value.Expires
}
}
return oldestElement, nil
}
// Choose method for priority ejector will return the oldest lowest priority element
func (p *PriorityBidderEjector) Choose(uids map[string]UIDEntry) (string, error) {
nonPriorityUids := getNonPriorityUids(uids, p.PriorityGroups, p.SyncersByBidder)
if err := p.checkSyncerPriority(nonPriorityUids); err != nil {
return "", err
}
if len(nonPriorityUids) > 0 {
return p.TieEjector.Choose(nonPriorityUids)
}
lowestPriorityGroup := p.PriorityGroups[len(p.PriorityGroups)-1]
if len(lowestPriorityGroup) == 1 {
uidToDelete := lowestPriorityGroup[0]
p.PriorityGroups = removeElementFromPriorityGroup(p.PriorityGroups, uidToDelete)
return uidToDelete, nil
}
lowestPriorityUids := getPriorityUids(lowestPriorityGroup, uids, p.SyncersByBidder)
uidToDelete, err := p.TieEjector.Choose(lowestPriorityUids)
if err != nil {
return "", err
}
p.PriorityGroups = removeElementFromPriorityGroup(p.PriorityGroups, uidToDelete)
return uidToDelete, nil
}
// updatePriorityGroup will remove the selected element from the priority groups, and will remove the entire priority group if it's empty
func removeElementFromPriorityGroup(priorityGroups [][]string, oldestElement string) [][]string {
lowestPriorityGroup := priorityGroups[len(priorityGroups)-1]
if len(lowestPriorityGroup) <= 1 {
return priorityGroups[:len(priorityGroups)-1]
}
for index, elem := range lowestPriorityGroup {
if elem == oldestElement {
updatedPriorityGroup := append(lowestPriorityGroup[:index], lowestPriorityGroup[index+1:]...)
priorityGroups[len(priorityGroups)-1] = updatedPriorityGroup
return priorityGroups
}
}
return priorityGroups
}
func getNonPriorityUids(uids map[string]UIDEntry, priorityGroups [][]string, syncersByBidder map[string]Syncer) map[string]UIDEntry {
// If no priority groups, then all keys in uids are non-priority
if len(priorityGroups) == 0 {
return uids
}
// Create map of keys that are a priority
isPriority := make(map[string]bool)
for _, group := range priorityGroups {
for _, bidder := range group {
if bidderSyncer, ok := syncersByBidder[bidder]; ok {
isPriority[bidderSyncer.Key()] = true
}
}
}
// Create a map for non-priority uids
nonPriorityUIDs := make(map[string]UIDEntry)
// Loop over uids and populate the nonPriorityUIDs map with non-priority keys
for key, value := range uids {
if _, found := isPriority[key]; !found {
nonPriorityUIDs[key] = value
}
}
return nonPriorityUIDs
}
func getPriorityUids(lowestPriorityGroup []string, uids map[string]UIDEntry, syncersByBidder map[string]Syncer) map[string]UIDEntry {
lowestPriorityUIDs := make(map[string]UIDEntry)
// Loop over lowestPriorityGroup and populate the lowestPriorityUIDs map
for _, bidder := range lowestPriorityGroup {
if bidderSyncer, ok := syncersByBidder[bidder]; ok {
if uidEntry, exists := uids[bidderSyncer.Key()]; exists {
lowestPriorityUIDs[bidderSyncer.Key()] = uidEntry
}
}
}
return lowestPriorityUIDs
}
func (p *PriorityBidderEjector) checkSyncerPriority(nonPriorityUids map[string]UIDEntry) error {
if len(nonPriorityUids) == 1 && !p.IsSyncerPriority && len(p.PriorityGroups) > 0 {
return errors.New("syncer key is not a priority, and there are only priority elements left")
}
return nil
}