Skip to content

Commit 7e9e1b1

Browse files
committed
store card as enum
1 parent 8c13486 commit 7e9e1b1

3 files changed

Lines changed: 144 additions & 76 deletions

File tree

golem-common/src/base_model/card/types.rs

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,7 @@ pub struct Card {
6363
}
6464

6565
#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
66+
#[cfg_attr(feature = "full", derive(desert_rust::BinaryCodec))]
6667
pub struct PolymorphicCard {
6768
pub card_id: CardId,
6869
pub parent_ids: Vec<CardId>,
@@ -75,6 +76,57 @@ pub struct PolymorphicCard {
7576
pub system_card: bool,
7677
}
7778

79+
#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
80+
#[cfg_attr(feature = "full", derive(desert_rust::BinaryCodec))]
81+
pub enum StoredCard {
82+
Concrete(Card),
83+
Polymorphic(PolymorphicCard),
84+
}
85+
86+
impl StoredCard {
87+
pub fn card_id(&self) -> CardId {
88+
match self {
89+
Self::Concrete(card) => card.card_id,
90+
Self::Polymorphic(card) => card.card_id,
91+
}
92+
}
93+
94+
pub fn parent_ids(&self) -> &[CardId] {
95+
match self {
96+
Self::Concrete(card) => &card.parent_ids,
97+
Self::Polymorphic(card) => &card.parent_ids,
98+
}
99+
}
100+
101+
pub fn expires_at(&self) -> Option<DateTime<Utc>> {
102+
match self {
103+
Self::Concrete(card) => card.expires_at,
104+
Self::Polymorphic(card) => card.expires_at,
105+
}
106+
}
107+
108+
pub fn system_card(&self) -> bool {
109+
match self {
110+
Self::Concrete(card) => card.system_card,
111+
Self::Polymorphic(card) => card.system_card,
112+
}
113+
}
114+
115+
pub fn into_concrete(self) -> Result<Card, Self> {
116+
match self {
117+
Self::Concrete(card) => Ok(card),
118+
other => Err(other),
119+
}
120+
}
121+
122+
pub fn into_polymorphic(self) -> Result<PolymorphicCard, Self> {
123+
match self {
124+
Self::Polymorphic(card) => Ok(card),
125+
other => Err(other),
126+
}
127+
}
128+
}
129+
78130
#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
79131
pub struct PolymorphicManifestCard {
80132
pub card_id: CardId,

golem-registry-service/src/repo/card.rs

Lines changed: 9 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -120,16 +120,16 @@ impl DbCardRepo<PostgresPool> {
120120
async fn insert_parent_links(
121121
tx: &mut PoolLabelledTransaction<PostgresPool>,
122122
card_id: Uuid,
123-
parent_ids: &[Uuid],
123+
parent_ids: &[CardId],
124124
) -> Result<(), CardRepoError> {
125125
for parent_id in parent_ids {
126126
tx.execute(
127127
sqlx::query("INSERT INTO card_parents (card_id, parent_id) VALUES ($1, $2)")
128128
.bind(card_id)
129-
.bind(parent_id),
129+
.bind(parent_id.0),
130130
)
131131
.await
132-
.to_error_on_foreign_key_violation(CardRepoError::ParentNotFound(*parent_id))?;
132+
.to_error_on_foreign_key_violation(CardRepoError::ParentNotFound(parent_id.0))?;
133133
}
134134

135135
Ok(())
@@ -248,7 +248,7 @@ impl DbCardRepo<PostgresPool> {
248248
tx: &mut PoolLabelledTransaction<PostgresPool>,
249249
record: CardRecord,
250250
) -> Result<CardRecord, CardRepoError> {
251-
Self::lock_parent_cards_for_create(tx, record.data.value().parent_ids.as_slice()).await?;
251+
Self::lock_parent_cards_for_create(tx, record.data.value().parent_ids()).await?;
252252

253253
let inserted: CardRecord = tx
254254
.fetch_one_as(
@@ -267,12 +267,7 @@ impl DbCardRepo<PostgresPool> {
267267
)
268268
.await?;
269269

270-
Self::insert_parent_links(
271-
tx,
272-
inserted.card_id,
273-
inserted.data.value().parent_ids.as_slice(),
274-
)
275-
.await?;
270+
Self::insert_parent_links(tx, inserted.card_id, inserted.data.value().parent_ids()).await?;
276271

277272
Ok(inserted)
278273
}
@@ -281,18 +276,18 @@ impl DbCardRepo<PostgresPool> {
281276
impl DbCardRepo<PostgresPool> {
282277
async fn lock_parent_cards_for_create(
283278
tx: &mut PoolLabelledTransaction<PostgresPool>,
284-
parent_ids: &[Uuid],
279+
parent_ids: &[CardId],
285280
) -> Result<(), CardRepoError> {
286281
for parent_id in parent_ids {
287282
let row = tx
288283
.fetch_optional(
289284
sqlx::query("SELECT card_id FROM cards WHERE card_id = $1 FOR UPDATE")
290-
.bind(*parent_id),
285+
.bind(parent_id.0),
291286
)
292287
.await?;
293288

294289
if row.is_none() {
295-
return Err(CardRepoError::ParentNotFound(*parent_id));
290+
return Err(CardRepoError::ParentNotFound(parent_id.0));
296291
}
297292
}
298293

@@ -303,7 +298,7 @@ impl DbCardRepo<PostgresPool> {
303298
impl DbCardRepo<SqlitePool> {
304299
async fn lock_parent_cards_for_create(
305300
_tx: &mut PoolLabelledTransaction<SqlitePool>,
306-
_parent_ids: &[Uuid],
301+
_parent_ids: &[CardId],
307302
) -> RepoResult<()> {
308303
// SQLite serializes write transactions, so there is no separate row-locking
309304
// primitive to use here. Missing parents are rejected by the card_parents FK.

golem-registry-service/src/repo/model/card.rs

Lines changed: 83 additions & 62 deletions
Original file line numberDiff line numberDiff line change
@@ -12,10 +12,12 @@
1212
// See the License for the specific language governing permissions and
1313
// limitations under the License.
1414

15+
use anyhow::anyhow;
1516
use chrono::{DateTime, Utc};
1617
use golem_common::error_forwarding;
1718
use golem_common::model::card::{
1819
Card, CardId, CardManagedBy, PermissionPattern, PolymorphicCard, PolymorphicPermissionPattern,
20+
StoredCard,
1921
};
2022
use golem_service_base::repo::{Blob, RepoError, SqlDateTime};
2123
use sqlx::FromRow;
@@ -37,15 +39,13 @@ error_forwarding!(CardRepoError, RepoError);
3739

3840
#[derive(Debug, Clone, PartialEq, Eq, desert_rust::BinaryCodec)]
3941
pub struct CardDataRecord {
40-
pub parent_ids: Vec<Uuid>,
41-
pub lower_positive: Vec<PermissionPattern>,
42-
pub lower_negative: Vec<PermissionPattern>,
43-
pub upper_positive: Vec<PermissionPattern>,
44-
pub upper_negative: Vec<PermissionPattern>,
45-
pub polymorphic_lower_positive: Vec<PolymorphicPermissionPattern>,
46-
pub polymorphic_lower_negative: Vec<PolymorphicPermissionPattern>,
47-
pub polymorphic_upper_positive: Vec<PolymorphicPermissionPattern>,
48-
pub polymorphic_upper_negative: Vec<PolymorphicPermissionPattern>,
42+
pub card: StoredCard,
43+
}
44+
45+
impl CardDataRecord {
46+
pub fn parent_ids(&self) -> &[CardId] {
47+
self.card.parent_ids()
48+
}
4949
}
5050

5151
#[derive(FromRow, Debug, Clone, PartialEq)]
@@ -62,19 +62,10 @@ impl TryFrom<CardRecord> for Card {
6262
type Error = RepoError;
6363

6464
fn try_from(value: CardRecord) -> Result<Self, Self::Error> {
65-
let data = value.data.into_value();
66-
67-
Ok(Card {
68-
card_id: CardId(value.card_id),
69-
parent_ids: data.parent_ids.into_iter().map(CardId).collect(),
70-
lower_positive: data.lower_positive,
71-
lower_negative: data.lower_negative,
72-
upper_positive: data.upper_positive,
73-
upper_negative: data.upper_negative,
74-
created_at: value.created_at.into(),
75-
expires_at: value.expires_at.map(Into::into),
76-
system_card: value.system_card,
77-
managed_by: value.managed_by.map(Blob::into_value),
65+
value.try_into_stored_card()?.into_concrete().map_err(|_| {
66+
RepoError::InternalError(anyhow!(
67+
"Cannot convert polymorphic card record to concrete card"
68+
))
7869
})
7970
}
8071
}
@@ -83,19 +74,22 @@ impl TryFrom<CardRecord> for PolymorphicCard {
8374
type Error = RepoError;
8475

8576
fn try_from(value: CardRecord) -> Result<Self, Self::Error> {
86-
let data = value.data.into_value();
87-
88-
Ok(PolymorphicCard {
89-
card_id: CardId(value.card_id),
90-
parent_ids: data.parent_ids.into_iter().map(CardId).collect(),
91-
lower_positive: data.polymorphic_lower_positive,
92-
lower_negative: data.polymorphic_lower_negative,
93-
upper_positive: data.polymorphic_upper_positive,
94-
upper_negative: data.polymorphic_upper_negative,
95-
created_at: value.created_at.into(),
96-
expires_at: value.expires_at.map(Into::into),
97-
system_card: value.system_card,
98-
})
77+
value
78+
.try_into_stored_card()?
79+
.into_polymorphic()
80+
.map_err(|_| {
81+
RepoError::InternalError(anyhow!(
82+
"Cannot convert concrete card record to polymorphic card"
83+
))
84+
})
85+
}
86+
}
87+
88+
impl TryFrom<CardRecord> for StoredCard {
89+
type Error = RepoError;
90+
91+
fn try_from(value: CardRecord) -> Result<Self, Self::Error> {
92+
value.try_into_stored_card()
9993
}
10094
}
10195

@@ -111,23 +105,27 @@ impl CardRecord {
111105
system_card: bool,
112106
managed_by: Option<CardManagedBy>,
113107
) -> Self {
108+
let card = Card {
109+
card_id,
110+
parent_ids,
111+
lower_positive,
112+
lower_negative,
113+
upper_positive,
114+
upper_negative,
115+
created_at: Utc::now(),
116+
expires_at,
117+
system_card,
118+
managed_by,
119+
};
114120
Self {
115-
card_id: card_id.0,
121+
card_id: card.card_id.0,
116122
data: Blob::new(CardDataRecord {
117-
parent_ids: parent_ids.into_iter().map(|id| id.0).collect(),
118-
lower_positive,
119-
lower_negative,
120-
upper_positive,
121-
upper_negative,
122-
polymorphic_lower_positive: Vec::new(),
123-
polymorphic_lower_negative: Vec::new(),
124-
polymorphic_upper_positive: Vec::new(),
125-
polymorphic_upper_negative: Vec::new(),
123+
card: StoredCard::Concrete(card.clone()),
126124
}),
127-
created_at: SqlDateTime::now(),
128-
expires_at: expires_at.map(Into::into),
129-
system_card,
130-
managed_by: managed_by.map(Blob::new),
125+
created_at: card.created_at.into(),
126+
expires_at: card.expires_at.map(Into::into),
127+
system_card: card.system_card,
128+
managed_by: card.managed_by.map(Blob::new),
131129
}
132130
}
133131

@@ -142,25 +140,48 @@ impl CardRecord {
142140
system_card: bool,
143141
managed_by: Option<CardManagedBy>,
144142
) -> Self {
143+
let card = PolymorphicCard {
144+
card_id,
145+
parent_ids,
146+
lower_positive,
147+
lower_negative,
148+
upper_positive,
149+
upper_negative,
150+
created_at: Utc::now(),
151+
expires_at,
152+
system_card,
153+
};
145154
Self {
146-
card_id: card_id.0,
155+
card_id: card.card_id.0,
147156
data: Blob::new(CardDataRecord {
148-
parent_ids: parent_ids.into_iter().map(|id| id.0).collect(),
149-
lower_positive: Vec::new(),
150-
lower_negative: Vec::new(),
151-
upper_positive: Vec::new(),
152-
upper_negative: Vec::new(),
153-
polymorphic_lower_positive: lower_positive,
154-
polymorphic_lower_negative: lower_negative,
155-
polymorphic_upper_positive: upper_positive,
156-
polymorphic_upper_negative: upper_negative,
157+
card: StoredCard::Polymorphic(card.clone()),
157158
}),
158-
created_at: SqlDateTime::now(),
159-
expires_at: expires_at.map(Into::into),
160-
system_card,
159+
created_at: card.created_at.into(),
160+
expires_at: card.expires_at.map(Into::into),
161+
system_card: card.system_card,
161162
managed_by: managed_by.map(Blob::new),
162163
}
163164
}
165+
166+
fn try_into_stored_card(self) -> Result<StoredCard, RepoError> {
167+
let mut card = self.data.into_value().card;
168+
match &mut card {
169+
StoredCard::Concrete(card) => {
170+
card.card_id = CardId(self.card_id);
171+
card.created_at = self.created_at.into();
172+
card.expires_at = self.expires_at.map(Into::into);
173+
card.system_card = self.system_card;
174+
card.managed_by = self.managed_by.map(Blob::into_value);
175+
}
176+
StoredCard::Polymorphic(card) => {
177+
card.card_id = CardId(self.card_id);
178+
card.created_at = self.created_at.into();
179+
card.expires_at = self.expires_at.map(Into::into);
180+
card.system_card = self.system_card;
181+
}
182+
}
183+
Ok(card)
184+
}
164185
}
165186

166187
#[cfg(test)]

0 commit comments

Comments
 (0)