Skip to content

Commit 283de6a

Browse files
committed
Fix migration yet again
De-duplicate both the "short" and "normal" versions.
1 parent 2283268 commit 283de6a

File tree

2 files changed

+60
-9
lines changed

2 files changed

+60
-9
lines changed

CHANGELOG.markdown

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,12 @@ This list is not comprehensive, and only lists new features and major changes,
55
but not every minor bugfix. The goatcounter.com service generally runs the
66
latest master.
77

8+
2021-04-13 v2.0.4
9+
-----------------
10+
- Deal with duplicate entries in the `user_agents` table in the migration
11+
instead of erroring out; mostly fixes a situation that could happen if you ran
12+
the broken migrations in 2.0.0 or 2.0.1.
13+
814
2021-04-02 v2.0.3
915
-----------------
1016
- Fix if you had already run the broken migrations in 2.0.0 or 2.0.1.

db/migrate/gomig/2020-12-31-1-user_agents.go

Lines changed: 54 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -17,21 +17,66 @@ import (
1717
"zgo.at/zli"
1818
)
1919

20+
type agentsT []struct {
21+
ID int64 `db:"user_agent_id"`
22+
UserAgent string `db:"ua"`
23+
}
24+
25+
func getAgents(ctx context.Context) (agentsT, error) {
26+
var agents agentsT
27+
err := zdb.Select(ctx, &agents, `select user_agent_id, ua from user_agents order by user_agent_id asc`)
28+
return agents, err
29+
}
30+
2031
func UserAgents(ctx context.Context) error {
21-
var agents []struct {
22-
ID int64 `db:"user_agent_id"`
23-
UserAgent string `db:"ua"`
24-
}
25-
err := zdb.Select(ctx, &agents,
26-
`select user_agent_id, ua from user_agents order by user_agent_id asc`)
32+
agents, err := getAgents(ctx)
2733
if err != nil {
2834
return err
2935
}
30-
3136
if len(agents) == 0 {
3237
return nil
3338
}
3439

40+
// Remove duplicates first.
41+
deleted := make(map[int64]struct{})
42+
for _, u := range agents {
43+
if _, ok := deleted[u.ID]; ok {
44+
continue
45+
}
46+
47+
if strings.ContainsRune(u.UserAgent, '~') {
48+
u.UserAgent = gadget.Unshorten(u.UserAgent)
49+
} else {
50+
u.UserAgent = gadget.Shorten(u.UserAgent)
51+
}
52+
53+
var dupes []int64
54+
err := zdb.Select(ctx, &dupes, `select user_agent_id from user_agents where ua=? and user_agent_id != ?`,
55+
u.UserAgent, u.ID)
56+
if err != nil {
57+
return err
58+
}
59+
if len(dupes) > 0 {
60+
fmt.Printf("%d → dupes: %v\n", u.ID, dupes)
61+
err := zdb.Exec(ctx, `update hits set user_agent_id=? where user_agent_id in (?)`, u.ID, dupes)
62+
if err != nil {
63+
return err
64+
}
65+
err = zdb.Exec(ctx, `delete from user_agents where user_agent_id in (?)`, dupes)
66+
if err != nil {
67+
return err
68+
}
69+
for _, d := range dupes {
70+
deleted[d] = struct{}{}
71+
}
72+
}
73+
}
74+
75+
agents, err = getAgents(ctx)
76+
if err != nil {
77+
return err
78+
}
79+
3580
errs := errors.NewGroup(1000)
3681
for i, u := range agents {
3782
if i%100 == 0 {
@@ -61,8 +106,8 @@ func UserAgents(ctx context.Context) error {
61106
bot := isbot.UserAgent(u.UserAgent)
62107
err = zdb.Exec(ctx, `update user_agents
63108
set browser_id=$1, system_id=$2, ua=$3, isbot=$4 where user_agent_id=$5`,
64-
browser.ID, system.ID, u.UserAgent, bot, u.ID)
65-
errs.Append(err)
109+
browser.ID, system.ID, gadget.Shorten(u.UserAgent), bot, u.ID)
110+
errs.Append(errors.Wrapf(err, "update user_agent %d", u.ID))
66111
}
67112
if errs.Len() > 0 {
68113
return errs

0 commit comments

Comments
 (0)