Skip to content

Commit 60dcaeb

Browse files
Select first before attempting an insert
As discovered in #773, Postgres increments the sequence even on aborted inserts. This creates extremely large gaps between our ids, which is a problem (as we then start overflowing the address space despite using a tiny amount of the address space, e.g. 2.5k / 65k IDs for artifacts, requiring an upgrade to i32 artifact IDs). sqlite does not seem to have this behavior, likely due to not supporting concurrent write transactions (which is the only reason postgres defaults to the eating behavior).
1 parent 2d9e78f commit 60dcaeb

File tree

1 file changed

+54
-31
lines changed

1 file changed

+54
-31
lines changed

database/src/pool/postgres.rs

Lines changed: 54 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -761,22 +761,30 @@ where
761761
let sid = self
762762
.conn()
763763
.query_opt(
764-
&self.statements().insert_pstat_series,
764+
&self.statements().select_pstat_series,
765765
&[&krate, &profile, &cache, &statistic],
766766
)
767767
.await
768768
.unwrap();
769769
let sid: i32 = match sid {
770770
Some(id) => id.get(0),
771-
None => self
772-
.conn()
773-
.query_one(
774-
&self.statements().select_pstat_series,
775-
&[&krate, &profile, &cache, &statistic],
776-
)
777-
.await
778-
.unwrap()
779-
.get(0),
771+
None => {
772+
self.conn()
773+
.query_opt(
774+
&self.statements().insert_pstat_series,
775+
&[&krate, &profile, &cache, &statistic],
776+
)
777+
.await
778+
.unwrap();
779+
self.conn()
780+
.query_one(
781+
&self.statements().select_pstat_series,
782+
&[&krate, &profile, &cache, &statistic],
783+
)
784+
.await
785+
.unwrap()
786+
.get(0)
787+
}
780788
};
781789
self.conn()
782790
.execute(
@@ -821,25 +829,32 @@ where
821829
),
822830
ArtifactId::Artifact(a) => (a.clone(), None, "release"),
823831
};
832+
let aid = self
833+
.conn()
834+
.query_opt("select id from artifact where name = $1", &[&name])
835+
.await
836+
.unwrap();
824837

825-
let aid = self.conn()
838+
let aid = match aid {
839+
Some(aid) => aid.get::<_, i32>(0) as u32,
840+
None => {
841+
self.conn()
826842
.query_opt("insert into artifact (name, date, type) VALUES ($1, $2, $3) ON CONFLICT DO NOTHING RETURNING id", &[
827843
&name,
828844
&date,
829845
&ty,
830846
])
831847
.await
832848
.unwrap();
833-
if let Some(row) = aid {
834-
return ArtifactIdNumber(row.get::<_, i32>(0) as u32);
835-
}
836-
ArtifactIdNumber(
837-
self.conn()
838-
.query_one("select id from artifact where name = $1", &[&name])
839-
.await
840-
.unwrap()
841-
.get::<_, i32>(0) as u32,
842-
)
849+
self.conn()
850+
.query_one("select id from artifact where name = $1", &[&name])
851+
.await
852+
.unwrap()
853+
.get::<_, i32>(0) as u32
854+
}
855+
};
856+
857+
ArtifactIdNumber(aid)
843858
}
844859

845860
async fn record_self_profile_query(
@@ -857,22 +872,30 @@ where
857872
let sid = self
858873
.conn()
859874
.query_opt(
860-
&self.statements().insert_self_query_series,
875+
&self.statements().select_self_query_series,
861876
&[&krate, &profile, &cache, &query],
862877
)
863878
.await
864879
.unwrap();
865880
let sid: i32 = match sid {
866881
Some(id) => id.get(0),
867-
None => self
868-
.conn()
869-
.query_one(
870-
&self.statements().select_self_query_series,
871-
&[&krate, &profile, &cache, &query],
872-
)
873-
.await
874-
.unwrap()
875-
.get(0),
882+
None => {
883+
self.conn()
884+
.query_one(
885+
&self.statements().insert_self_query_series,
886+
&[&krate, &profile, &cache, &query],
887+
)
888+
.await
889+
.unwrap();
890+
self.conn()
891+
.query_one(
892+
&self.statements().select_self_query_series,
893+
&[&krate, &profile, &cache, &query],
894+
)
895+
.await
896+
.unwrap()
897+
.get(0)
898+
}
876899
};
877900
self.conn()
878901
.execute(

0 commit comments

Comments
 (0)