fix(milestones): use previous spelling for milestone types (#8886)

# Which Problems Are Solved

https://github.com/zitadel/zitadel/pull/8788 accidentally changed the
spelling of milestone types from PascalCase to snake_case. This breaks
systems where `milestone.pushed` events already exist.

# How the Problems Are Solved

- Use PascalCase again
- Prefix event types with v2. (Previous pushed event type was anyway
ignored).
- Create `milstones3` projection

# Additional Changes

None

# Additional Context

relates to #8788

(cherry picked from commit fb6579e4565aa0e74ed3f3f5ea5ee7d8c67d78a2)
This commit is contained in:
Livio Spring 2024-11-11 12:28:27 +01:00
parent 0aba000355
commit a062fd7e48
No known key found for this signature in database
GPG Key ID: 26BB1C2FA5952CF0
8 changed files with 51 additions and 54 deletions

View File

@ -23,7 +23,7 @@ var (
getProjectedMilestones string getProjectedMilestones string
) )
type FillV2Milestones struct { type FillV3Milestones struct {
dbClient *database.DB dbClient *database.DB
eventstore *eventstore.Eventstore eventstore *eventstore.Eventstore
} }
@ -34,7 +34,7 @@ type instanceMilestone struct {
Pushed *time.Time Pushed *time.Time
} }
func (mig *FillV2Milestones) Execute(ctx context.Context, _ eventstore.Event) error { func (mig *FillV3Milestones) Execute(ctx context.Context, _ eventstore.Event) error {
im, err := mig.getProjectedMilestones(ctx) im, err := mig.getProjectedMilestones(ctx)
if err != nil { if err != nil {
return err return err
@ -42,7 +42,7 @@ func (mig *FillV2Milestones) Execute(ctx context.Context, _ eventstore.Event) er
return mig.pushEventsByInstance(ctx, im) return mig.pushEventsByInstance(ctx, im)
} }
func (mig *FillV2Milestones) getProjectedMilestones(ctx context.Context) (map[string][]instanceMilestone, error) { func (mig *FillV3Milestones) getProjectedMilestones(ctx context.Context) (map[string][]instanceMilestone, error) {
type row struct { type row struct {
InstanceID string InstanceID string
Type milestone.Type Type milestone.Type
@ -73,7 +73,7 @@ func (mig *FillV2Milestones) getProjectedMilestones(ctx context.Context) (map[st
// pushEventsByInstance creates the v2 milestone events by instance. // pushEventsByInstance creates the v2 milestone events by instance.
// This prevents we will try to push 6*N(instance) events in one push. // This prevents we will try to push 6*N(instance) events in one push.
func (mig *FillV2Milestones) pushEventsByInstance(ctx context.Context, milestoneMap map[string][]instanceMilestone) error { func (mig *FillV3Milestones) pushEventsByInstance(ctx context.Context, milestoneMap map[string][]instanceMilestone) error {
// keep a deterministic order by instance ID. // keep a deterministic order by instance ID.
order := make([]string, 0, len(milestoneMap)) order := make([]string, 0, len(milestoneMap))
for k := range milestoneMap { for k := range milestoneMap {
@ -81,8 +81,8 @@ func (mig *FillV2Milestones) pushEventsByInstance(ctx context.Context, milestone
} }
slices.Sort(order) slices.Sort(order)
for _, instanceID := range order { for i, instanceID := range order {
logging.WithFields("instance_id", instanceID, "migration", mig.String()).Info("filter existing milestone events") logging.WithFields("instance_id", instanceID, "migration", mig.String(), "progress", fmt.Sprintf("%d/%d", i+1, len(order))).Info("filter existing milestone events")
// because each Push runs in a separate TX, we need to make sure that events // because each Push runs in a separate TX, we need to make sure that events
// from a partially executed migration are pushed again. // from a partially executed migration are pushed again.
@ -113,6 +113,6 @@ func (mig *FillV2Milestones) pushEventsByInstance(ctx context.Context, milestone
return nil return nil
} }
func (mig *FillV2Milestones) String() string { func (mig *FillV3Milestones) String() string {
return "36_fill_v2_milestones" return "36_fill_v3_milestones"
} }

View File

@ -122,7 +122,7 @@ type Steps struct {
s33SMSConfigs3TwilioAddVerifyServiceSid *SMSConfigs3TwilioAddVerifyServiceSid s33SMSConfigs3TwilioAddVerifyServiceSid *SMSConfigs3TwilioAddVerifyServiceSid
s34AddCacheSchema *AddCacheSchema s34AddCacheSchema *AddCacheSchema
s35AddPositionToIndexEsWm *AddPositionToIndexEsWm s35AddPositionToIndexEsWm *AddPositionToIndexEsWm
s36FillV2Milestones *FillV2Milestones s36FillV2Milestones *FillV3Milestones
s37Apps7OIDConfigsBackChannelLogoutURI *Apps7OIDConfigsBackChannelLogoutURI s37Apps7OIDConfigsBackChannelLogoutURI *Apps7OIDConfigsBackChannelLogoutURI
s38BackChannelLogoutNotificationStart *BackChannelLogoutNotificationStart s38BackChannelLogoutNotificationStart *BackChannelLogoutNotificationStart
} }

View File

@ -165,7 +165,7 @@ func Setup(ctx context.Context, config *Config, steps *Steps, masterKey string)
steps.s33SMSConfigs3TwilioAddVerifyServiceSid = &SMSConfigs3TwilioAddVerifyServiceSid{dbClient: esPusherDBClient} steps.s33SMSConfigs3TwilioAddVerifyServiceSid = &SMSConfigs3TwilioAddVerifyServiceSid{dbClient: esPusherDBClient}
steps.s34AddCacheSchema = &AddCacheSchema{dbClient: queryDBClient} steps.s34AddCacheSchema = &AddCacheSchema{dbClient: queryDBClient}
steps.s35AddPositionToIndexEsWm = &AddPositionToIndexEsWm{dbClient: esPusherDBClient} steps.s35AddPositionToIndexEsWm = &AddPositionToIndexEsWm{dbClient: esPusherDBClient}
steps.s36FillV2Milestones = &FillV2Milestones{dbClient: queryDBClient, eventstore: eventstoreClient} steps.s36FillV2Milestones = &FillV3Milestones{dbClient: queryDBClient, eventstore: eventstoreClient}
steps.s37Apps7OIDConfigsBackChannelLogoutURI = &Apps7OIDConfigsBackChannelLogoutURI{dbClient: esPusherDBClient} steps.s37Apps7OIDConfigsBackChannelLogoutURI = &Apps7OIDConfigsBackChannelLogoutURI{dbClient: esPusherDBClient}
steps.s38BackChannelLogoutNotificationStart = &BackChannelLogoutNotificationStart{dbClient: esPusherDBClient, esClient: eventstoreClient} steps.s38BackChannelLogoutNotificationStart = &BackChannelLogoutNotificationStart{dbClient: esPusherDBClient, esClient: eventstoreClient}

View File

@ -11,14 +11,14 @@ import (
var ( var (
expectedMilestoneQuery = regexp.QuoteMeta(` expectedMilestoneQuery = regexp.QuoteMeta(`
SELECT projections.milestones2.instance_id, SELECT projections.milestones3.instance_id,
projections.instance_domains.domain, projections.instance_domains.domain,
projections.milestones2.reached_date, projections.milestones3.reached_date,
projections.milestones2.last_pushed_date, projections.milestones3.last_pushed_date,
projections.milestones2.type, projections.milestones3.type,
COUNT(*) OVER () COUNT(*) OVER ()
FROM projections.milestones2 AS OF SYSTEM TIME '-1 ms' FROM projections.milestones3 AS OF SYSTEM TIME '-1 ms'
LEFT JOIN projections.instance_domains ON projections.milestones2.instance_id = projections.instance_domains.instance_id LEFT JOIN projections.instance_domains ON projections.milestones3.instance_id = projections.instance_domains.instance_id
`) `)
milestoneCols = []string{ milestoneCols = []string{

View File

@ -10,7 +10,7 @@ import (
) )
const ( const (
MilestonesProjectionTable = "projections.milestones2" MilestonesProjectionTable = "projections.milestones3"
MilestoneColumnInstanceID = "instance_id" MilestoneColumnInstanceID = "instance_id"
MilestoneColumnType = "type" MilestoneColumnType = "type"
@ -77,9 +77,6 @@ func (p *milestoneProjection) reducePushed(event eventstore.Event) (*handler.Sta
if err != nil { if err != nil {
return nil, err return nil, err
} }
if e.Agg.Version != milestone.AggregateVersion {
return handler.NewNoOpStatement(event), nil // Skip v1 events.
}
if e.MilestoneType != milestone.InstanceDeleted { if e.MilestoneType != milestone.InstanceDeleted {
return handler.NewUpdateStatement( return handler.NewUpdateStatement(
event, event,

View File

@ -31,7 +31,7 @@ func TestMilestonesProjection_reduces(t *testing.T) {
event: getEvent(timedTestEvent( event: getEvent(timedTestEvent(
milestone.ReachedEventType, milestone.ReachedEventType,
milestone.AggregateType, milestone.AggregateType,
[]byte(`{"type": "instance_created"}`), []byte(`{"type": "InstanceCreated"}`),
now, now,
withVersion(milestone.AggregateVersion), withVersion(milestone.AggregateVersion),
), milestone.ReachedEventMapper), ), milestone.ReachedEventMapper),
@ -43,7 +43,7 @@ func TestMilestonesProjection_reduces(t *testing.T) {
executer: &testExecuter{ executer: &testExecuter{
executions: []execution{ executions: []execution{
{ {
expectedStmt: "INSERT INTO projections.milestones2 (instance_id, type, reached_date) VALUES ($1, $2, $3)", expectedStmt: "INSERT INTO projections.milestones3 (instance_id, type, reached_date) VALUES ($1, $2, $3)",
expectedArgs: []interface{}{ expectedArgs: []interface{}{
"instance-id", "instance-id",
milestone.InstanceCreated, milestone.InstanceCreated,
@ -60,7 +60,7 @@ func TestMilestonesProjection_reduces(t *testing.T) {
event: getEvent(timedTestEvent( event: getEvent(timedTestEvent(
milestone.ReachedEventType, milestone.ReachedEventType,
milestone.AggregateType, milestone.AggregateType,
[]byte(`{"type": "instance_created", "reachedDate":"2006-01-02T15:04:05Z"}`), []byte(`{"type": "InstanceCreated", "reachedDate":"2006-01-02T15:04:05Z"}`),
now, now,
withVersion(milestone.AggregateVersion), withVersion(milestone.AggregateVersion),
), milestone.ReachedEventMapper), ), milestone.ReachedEventMapper),
@ -72,7 +72,7 @@ func TestMilestonesProjection_reduces(t *testing.T) {
executer: &testExecuter{ executer: &testExecuter{
executions: []execution{ executions: []execution{
{ {
expectedStmt: "INSERT INTO projections.milestones2 (instance_id, type, reached_date) VALUES ($1, $2, $3)", expectedStmt: "INSERT INTO projections.milestones3 (instance_id, type, reached_date) VALUES ($1, $2, $3)",
expectedArgs: []interface{}{ expectedArgs: []interface{}{
"instance-id", "instance-id",
milestone.InstanceCreated, milestone.InstanceCreated,
@ -89,7 +89,7 @@ func TestMilestonesProjection_reduces(t *testing.T) {
event: getEvent(timedTestEvent( event: getEvent(timedTestEvent(
milestone.PushedEventType, milestone.PushedEventType,
milestone.AggregateType, milestone.AggregateType,
[]byte(`{"type": "project_created"}`), []byte(`{"type": "ProjectCreated"}`),
now, now,
withVersion(milestone.AggregateVersion), withVersion(milestone.AggregateVersion),
), milestone.PushedEventMapper), ), milestone.PushedEventMapper),
@ -101,7 +101,7 @@ func TestMilestonesProjection_reduces(t *testing.T) {
executer: &testExecuter{ executer: &testExecuter{
executions: []execution{ executions: []execution{
{ {
expectedStmt: "UPDATE projections.milestones2 SET last_pushed_date = $1 WHERE (instance_id = $2) AND (type = $3)", expectedStmt: "UPDATE projections.milestones3 SET last_pushed_date = $1 WHERE (instance_id = $2) AND (type = $3)",
expectedArgs: []interface{}{ expectedArgs: []interface{}{
now, now,
"instance-id", "instance-id",
@ -118,7 +118,7 @@ func TestMilestonesProjection_reduces(t *testing.T) {
event: getEvent(timedTestEvent( event: getEvent(timedTestEvent(
milestone.PushedEventType, milestone.PushedEventType,
milestone.AggregateType, milestone.AggregateType,
[]byte(`{"type": "project_created", "pushedDate":"2006-01-02T15:04:05Z"}`), []byte(`{"type": "ProjectCreated", "pushedDate":"2006-01-02T15:04:05Z"}`),
now, now,
withVersion(milestone.AggregateVersion), withVersion(milestone.AggregateVersion),
), milestone.PushedEventMapper), ), milestone.PushedEventMapper),
@ -130,7 +130,7 @@ func TestMilestonesProjection_reduces(t *testing.T) {
executer: &testExecuter{ executer: &testExecuter{
executions: []execution{ executions: []execution{
{ {
expectedStmt: "UPDATE projections.milestones2 SET last_pushed_date = $1 WHERE (instance_id = $2) AND (type = $3)", expectedStmt: "UPDATE projections.milestones3 SET last_pushed_date = $1 WHERE (instance_id = $2) AND (type = $3)",
expectedArgs: []interface{}{ expectedArgs: []interface{}{
date, date,
"instance-id", "instance-id",
@ -147,7 +147,7 @@ func TestMilestonesProjection_reduces(t *testing.T) {
event: getEvent(testEvent( event: getEvent(testEvent(
milestone.PushedEventType, milestone.PushedEventType,
milestone.AggregateType, milestone.AggregateType,
[]byte(`{"type": "instance_deleted"}`), []byte(`{"type": "InstanceDeleted"}`),
withVersion(milestone.AggregateVersion), withVersion(milestone.AggregateVersion),
), milestone.PushedEventMapper), ), milestone.PushedEventMapper),
}, },
@ -158,7 +158,7 @@ func TestMilestonesProjection_reduces(t *testing.T) {
executer: &testExecuter{ executer: &testExecuter{
executions: []execution{ executions: []execution{
{ {
expectedStmt: "DELETE FROM projections.milestones2 WHERE (instance_id = $1)", expectedStmt: "DELETE FROM projections.milestones3 WHERE (instance_id = $1)",
expectedArgs: []interface{}{ expectedArgs: []interface{}{
"instance-id", "instance-id",
}, },

View File

@ -7,7 +7,7 @@ import (
"github.com/zitadel/zitadel/internal/eventstore" "github.com/zitadel/zitadel/internal/eventstore"
) )
//go:generate enumer -type Type -json -linecomment -transform=snake //go:generate enumer -type Type -json -linecomment
type Type int type Type int
const ( const (
@ -20,7 +20,7 @@ const (
) )
const ( const (
eventTypePrefix = "milestone." eventTypePrefix = "milestone.v2."
ReachedEventType = eventTypePrefix + "reached" ReachedEventType = eventTypePrefix + "reached"
PushedEventType = eventTypePrefix + "pushed" PushedEventType = eventTypePrefix + "pushed"
) )

View File

@ -1,4 +1,4 @@
// Code generated by "enumer -type Type -json -linecomment -transform=snake"; DO NOT EDIT. // Code generated by "enumer -type Type -json -linecomment"; DO NOT EDIT.
package milestone package milestone
@ -8,11 +8,11 @@ import (
"strings" "strings"
) )
const _TypeName = "instance_createdauthentication_succeeded_on_instanceproject_createdapplication_createdauthentication_succeeded_on_applicationinstance_deleted" const _TypeName = "InstanceCreatedAuthenticationSucceededOnInstanceProjectCreatedApplicationCreatedAuthenticationSucceededOnApplicationInstanceDeleted"
var _TypeIndex = [...]uint8{0, 16, 52, 67, 86, 125, 141} var _TypeIndex = [...]uint8{0, 15, 48, 62, 80, 116, 131}
const _TypeLowerName = "instance_createdauthentication_succeeded_on_instanceproject_createdapplication_createdauthentication_succeeded_on_applicationinstance_deleted" const _TypeLowerName = "instancecreatedauthenticationsucceededoninstanceprojectcreatedapplicationcreatedauthenticationsucceededonapplicationinstancedeleted"
func (i Type) String() string { func (i Type) String() string {
i -= 1 i -= 1
@ -37,27 +37,27 @@ func _TypeNoOp() {
var _TypeValues = []Type{InstanceCreated, AuthenticationSucceededOnInstance, ProjectCreated, ApplicationCreated, AuthenticationSucceededOnApplication, InstanceDeleted} var _TypeValues = []Type{InstanceCreated, AuthenticationSucceededOnInstance, ProjectCreated, ApplicationCreated, AuthenticationSucceededOnApplication, InstanceDeleted}
var _TypeNameToValueMap = map[string]Type{ var _TypeNameToValueMap = map[string]Type{
_TypeName[0:16]: InstanceCreated, _TypeName[0:15]: InstanceCreated,
_TypeLowerName[0:16]: InstanceCreated, _TypeLowerName[0:15]: InstanceCreated,
_TypeName[16:52]: AuthenticationSucceededOnInstance, _TypeName[15:48]: AuthenticationSucceededOnInstance,
_TypeLowerName[16:52]: AuthenticationSucceededOnInstance, _TypeLowerName[15:48]: AuthenticationSucceededOnInstance,
_TypeName[52:67]: ProjectCreated, _TypeName[48:62]: ProjectCreated,
_TypeLowerName[52:67]: ProjectCreated, _TypeLowerName[48:62]: ProjectCreated,
_TypeName[67:86]: ApplicationCreated, _TypeName[62:80]: ApplicationCreated,
_TypeLowerName[67:86]: ApplicationCreated, _TypeLowerName[62:80]: ApplicationCreated,
_TypeName[86:125]: AuthenticationSucceededOnApplication, _TypeName[80:116]: AuthenticationSucceededOnApplication,
_TypeLowerName[86:125]: AuthenticationSucceededOnApplication, _TypeLowerName[80:116]: AuthenticationSucceededOnApplication,
_TypeName[125:141]: InstanceDeleted, _TypeName[116:131]: InstanceDeleted,
_TypeLowerName[125:141]: InstanceDeleted, _TypeLowerName[116:131]: InstanceDeleted,
} }
var _TypeNames = []string{ var _TypeNames = []string{
_TypeName[0:16], _TypeName[0:15],
_TypeName[16:52], _TypeName[15:48],
_TypeName[52:67], _TypeName[48:62],
_TypeName[67:86], _TypeName[62:80],
_TypeName[86:125], _TypeName[80:116],
_TypeName[125:141], _TypeName[116:131],
} }
// TypeString retrieves an enum value from the enum constants string name. // TypeString retrieves an enum value from the enum constants string name.