-
-
Notifications
You must be signed in to change notification settings - Fork 739
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
feat: Feature lifecycle sql store #6790
Changes from 3 commits
444f3a2
e14d2d9
07351ae
52cbb23
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,52 @@ | ||
import type { | ||
FeatureLifecycleStage, | ||
IFeatureLifecycleStore, | ||
FeatureLifecycleView, | ||
StageName, | ||
} from './feature-lifecycle-store-type'; | ||
import type { Db } from '../../db/db'; | ||
|
||
type DBType = { | ||
feature: string; | ||
stage: StageName; | ||
created_at: Date; | ||
}; | ||
|
||
export class FeatureLifecycleStore implements IFeatureLifecycleStore { | ||
private db: Db; | ||
|
||
constructor(db: Db) { | ||
this.db = db; | ||
} | ||
|
||
async insert(featureLifecycleStage: FeatureLifecycleStage): Promise<void> { | ||
await this.db('feature_lifecycles') | ||
.insert({ | ||
feature: featureLifecycleStage.feature, | ||
stage: featureLifecycleStage.stage, | ||
}) | ||
.returning('*') | ||
.onConflict(['feature', 'stage']) | ||
.ignore(); | ||
} | ||
|
||
async get(feature: string): Promise<FeatureLifecycleView> { | ||
const results = await this.db('feature_lifecycles') | ||
.where({ feature }) | ||
.orderBy('created_at', 'asc'); | ||
|
||
return results.map(({ stage, created_at }: DBType) => ({ | ||
stage, | ||
enteredStageAt: created_at, | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. will probably rename enteredStageAt to createdAt in the service and openapi |
||
})); | ||
} | ||
|
||
async stageExists(stage: FeatureLifecycleStage): Promise<boolean> { | ||
const result = await this.db.raw( | ||
`SELECT EXISTS(SELECT 1 FROM feature_lifecycles WHERE stage = ? and feature = ?) AS present`, | ||
[stage.stage, stage.feature], | ||
); | ||
const { present } = result.rows[0]; | ||
return present; | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
'use strict'; | ||
|
||
exports.up = function(db, cb) { | ||
db.runSql( | ||
` | ||
CREATE TABLE IF NOT EXISTS feature_lifecycles ( | ||
feature VARCHAR(255) NOT NULL REFERENCES features(name) ON DELETE CASCADE, | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. we want to delete feature lifecycle when feature is removed |
||
stage VARCHAR(255) NULL, | ||
created_at TIMESTAMP WITH TIME ZONE default now(), | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. sticking to generic name instead of specific stage_entered_at There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. using timestamp with timezone to have the same type as features table |
||
PRIMARY KEY (feature, stage) | ||
);`, | ||
cb, | ||
); | ||
}; | ||
|
||
exports.down = function(db, cb) { | ||
db.runSql('DROP TABLE IF EXISTS feature_lifecycles;', cb); | ||
}; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
prevent double inserts in fake impl