From df7a1f43745abdd06b617f0a1bcc1be027d318d8 Mon Sep 17 00:00:00 2001 From: Naoki Kishi Date: Thu, 6 Aug 2020 22:13:17 +0900 Subject: [PATCH] =?UTF-8?q?=E5=86=8D=E7=94=9F=E7=B5=82=E4=BA=86=E6=99=82?= =?UTF-8?q?=E3=81=AB=E6=96=B0=E8=A6=8F=E3=81=AB=E6=9B=B2=E3=82=92Spotify?= =?UTF-8?q?=E3=81=AE=E3=82=AD=E3=83=A5=E3=83=BC=E3=81=AB=E8=BF=BD=E5=8A=A0?= =?UTF-8?q?=E3=81=99=E3=82=8B=E5=87=A6=E7=90=86=E3=81=AFhandleWaitTimerExp?= =?UTF-8?q?ired=E3=81=AE=E6=96=B9=E3=81=A7=E8=A1=8C=E3=81=86=E3=81=93?= =?UTF-8?q?=E3=81=A8=E3=81=A7=E3=80=81active=20device=20not=20found?= =?UTF-8?q?=E3=81=AE=E3=81=A8=E3=81=8D=E3=81=AB=E6=AD=A3=E3=81=97=E3=81=8F?= =?UTF-8?q?INTERRUPT=E5=87=A6=E7=90=86=E3=81=8C=E8=A1=8C=E3=82=8F=E3=82=8C?= =?UTF-8?q?=E3=82=8B=E3=82=88=E3=81=86=E3=81=AB=E3=81=99=E3=82=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- usecase/session_timer.go | 35 ++++----- usecase/session_timer_test.go | 133 +++++++++++++++------------------- 2 files changed, 76 insertions(+), 92 deletions(-) diff --git a/usecase/session_timer.go b/usecase/session_timer.go index 47c01b6f..aff3c581 100644 --- a/usecase/session_timer.go +++ b/usecase/session_timer.go @@ -93,11 +93,12 @@ func (s *SessionTimerUseCase) startTrackEndTrigger(ctx context.Context, sessionI func (s *SessionTimerUseCase) handleWaitTimerExpired(ctx context.Context, sessionID string, triggerAfterTrackEnd *entity.SyncCheckTimer, currentOperation currentOperation) error { logger := log.New() + logger.Debugj(map[string]interface{}{"message": "currentOperation", "currentOperation": currentOperation}) playingInfo, err := s.playerCli.CurrentlyPlaying(ctx) if err != nil { logger.Errorj(map[string]interface{}{ - "message": "startTrackEndTrigger: failed to get currently playing info", + "message": "handleWaitTimerExpired: failed to get currently playing info", "sessionID": sessionID, "error": err.Error(), }) @@ -107,7 +108,7 @@ func (s *SessionTimerUseCase) handleWaitTimerExpired(ctx context.Context, sessio sess, err := s.sessionRepo.FindByID(ctx, sessionID) if err != nil { logger.Errorj(map[string]interface{}{ - "message": "startTrackEndTrigger: failed to get session", + "message": "handleWaitTimerExpired: failed to get session", "sessionID": sessionID, "error": err.Error(), }) @@ -118,7 +119,7 @@ func (s *SessionTimerUseCase) handleWaitTimerExpired(ctx context.Context, sessio s.handleInterrupt(sess) if err := s.sessionRepo.Update(ctx, sess); err != nil { logger.Errorj(map[string]interface{}{ - "message": "startTrackEndTrigger: failed to update session after handleInterrupt", + "message": "handleWaitTimerExpired: failed to update session after IsPlayingCorrectTrack and handleInterrupt", "sessionID": sessionID, "error": err.Error(), }) @@ -127,7 +128,20 @@ func (s *SessionTimerUseCase) handleWaitTimerExpired(ctx context.Context, sessio return fmt.Errorf("session interrupt") } - logger.Debugj(map[string]interface{}{"message": "currentOperation", "currentOperation": currentOperation}) + track := sess.TrackURIShouldBeAddedWhenHandleTrackEnd() + if track != "" { + if err := s.playerCli.Enqueue(ctx, track, sess.DeviceID); err != nil { + s.handleInterrupt(sess) + if err := s.sessionRepo.Update(ctx, sess); err != nil { + logger.Errorj(map[string]interface{}{ + "message": "handleWaitTimerExpired: failed to update session after Enqueue and handleInterrupt", + "sessionID": sessionID, + "error": err.Error(), + }) + return fmt.Errorf("failed to enqueue track") + } + } + } switch currentOperation { case operationNextTrack: @@ -210,19 +224,6 @@ func (s *SessionTimerUseCase) handleTrackEndTx(sessionID string) func(ctx contex }, nil } - track := sess.TrackURIShouldBeAddedWhenHandleTrackEnd() - if track != "" { - // TODO: Spotifyアプリを閉じた後、ずっとRelaymを開かないとINTERRUPTにならずにここまでたどり着いて - // active device not foundになってしまう - // そのときstateはPLAYのままなので表示がバグる - if err := s.playerCli.Enqueue(ctx, track, sess.DeviceID); err != nil { - return &handleTrackEndResponse{ - nextTrack: false, - err: fmt.Errorf("call add queue api trackURI=%s: %w", track, err), - }, nil - } - } - logger.Debugj(map[string]interface{}{"message": "next track", "sessionID": sess.ID, "queueHead": sess.QueueHead}) return &handleTrackEndResponse{nextTrack: true, err: nil}, nil diff --git a/usecase/session_timer_test.go b/usecase/session_timer_test.go index b687e812..b8446d11 100644 --- a/usecase/session_timer_test.go +++ b/usecase/session_timer_test.go @@ -119,80 +119,6 @@ func TestSessionTimerUseCase_handleTrackEndTx(t *testing.T) { wantNextTrack: true, wantErr: false, }, - { - name: "次の曲が存在し、次に再生される曲の二曲先の曲が存在するときはNEXTTRACKイベントが送られて、次の再生状態に遷移し、同時に二曲先の曲がSpotifyのqueueに積まれる", - sessionID: "sessionID", - prepareMockPlayerFn: func(m *mock_spotify.MockPlayer) { - m.EXPECT().Enqueue(gomock.Any(), "spotify:track:3", "deviceID").Return(nil) - }, - prepareMockPusherFn: func(m *mock_event.MockPusher) { - }, - prepareMockUserRepoFn: func(m *mock_repository.MockUser) {}, - prepareMockSessionRepoFn: func(m *mock_repository.MockSession) { - m.EXPECT().FindByIDForUpdate(gomock.Any(), "sessionID").Return(&entity.Session{ - ID: "sessionID", - Name: "name", - CreatorID: "creatorID", - DeviceID: "deviceID", - StateType: entity.Play, - QueueHead: 0, - QueueTracks: []*entity.QueueTrack{ - { - Index: 0, - URI: "spotify:track:asfafefea", - SessionID: "sessionID", - }, - { - Index: 1, - URI: "spotify:track:06QTSGUEgcmKwiEJ0IMPig", - SessionID: "sessionID", - }, - { - Index: 2, - URI: "spotify:track:2", - SessionID: "sessionID", - }, - { - Index: 3, - URI: "spotify:track:3", - SessionID: "sessionID", - }, - }, - }, nil) - m.EXPECT().Update(gomock.Any(), &entity.Session{ - ID: "sessionID", - Name: "name", - CreatorID: "creatorID", - DeviceID: "deviceID", - StateType: entity.Play, - QueueHead: 1, - QueueTracks: []*entity.QueueTrack{ - { - Index: 0, - URI: "spotify:track:asfafefea", - SessionID: "sessionID", - }, - { - Index: 1, - URI: "spotify:track:06QTSGUEgcmKwiEJ0IMPig", - SessionID: "sessionID", - }, - { - Index: 2, - URI: "spotify:track:2", - SessionID: "sessionID", - }, - { - Index: 3, - URI: "spotify:track:3", - SessionID: "sessionID", - }, - }, - }).Return(nil) - }, - wantNextTrack: true, - wantErr: false, - }, { name: "次の曲が存在するが、実際には違う曲が流れていた場合はINTERRUPTイベントが送られる", sessionID: "sessionID", @@ -455,7 +381,61 @@ func TestSessionTimerUseCase_handleWaitTimerExpired(t *testing.T) { wantErr: false, }, { - name: "Spotifyとの同期が取れていることが確認されると、currentOperationがNextTrackの時はイベントは送信されない", + name: "Spotifyとの同期が取れていることが確認されると、currentOperationがNextTrackの時はイベントが送信される", + sessionID: "sessionID", + currentOperation: "NextTrack", + prepareMockPlayerFn: func(m *mock_spotify.MockPlayer) { + m.EXPECT().CurrentlyPlaying(gomock.Any()).Return(&entity.CurrentPlayingInfo{ + Playing: true, + Progress: 10000000, + Track: &entity.Track{ + URI: "spotify:track:06QTSGUEgcmKwiEJ0IMPig", + ID: "06QTSGUEgcmKwiEJ0IMPig", + Name: "Borderland", + Duration: 213066000000, + Artists: []*entity.Artist{{Name: "MONOEYES"}}, + URL: "https://open.spotify.com/track/06QTSGUEgcmKwiEJ0IMPig", + Album: &entity.Album{ + Name: "Interstate 46 E.P.", + Images: []*entity.AlbumImage{ + { + URL: "https://i.scdn.co/image/ab67616d0000b273b48630d6efcebca2596120c4", + Height: 640, + Width: 640, + }, + }, + }, + }, + }, nil) + }, + prepareMockPusherFn: func(m *mock_event.MockPusher) { + m.EXPECT().Push(&event.PushMessage{ + SessionID: "sessionID", + Msg: entity.NewEventNextTrack(1), + }) + }, + prepareMockUserRepoFn: func(m *mock_repository.MockUser) {}, + prepareMockSessionRepoFn: func(m *mock_repository.MockSession) { + m.EXPECT().FindByID(gomock.Any(), "sessionID").Return(&entity.Session{ + ID: "sessionID", + Name: "name", + CreatorID: "creatorID", + DeviceID: "deviceID", + StateType: "PLAY", + QueueHead: 1, + QueueTracks: []*entity.QueueTrack{ + {Index: 0, URI: "spotify:track:5uQ0vKy2973Y9IUCd1wMEF"}, + {Index: 1, URI: "spotify:track:06QTSGUEgcmKwiEJ0IMPig"}, + }, + ExpiredAt: time.Time{}, + AllowToControlByOthers: false, + ProgressWhenPaused: 0, + }, nil) + }, + wantErr: false, + }, + { + name: "Spotifyとの同期が取れていることが確認されると、新しく追加すべき曲がSpotifyのキューに追加される", sessionID: "sessionID", currentOperation: "NextTrack", prepareMockPlayerFn: func(m *mock_spotify.MockPlayer) { @@ -481,6 +461,7 @@ func TestSessionTimerUseCase_handleWaitTimerExpired(t *testing.T) { }, }, }, nil) + m.EXPECT().Enqueue(gomock.Any(), "spotify:track:track3", "deviceID").Return(nil) }, prepareMockPusherFn: func(m *mock_event.MockPusher) { m.EXPECT().Push(&event.PushMessage{ @@ -500,6 +481,8 @@ func TestSessionTimerUseCase_handleWaitTimerExpired(t *testing.T) { QueueTracks: []*entity.QueueTrack{ {Index: 0, URI: "spotify:track:5uQ0vKy2973Y9IUCd1wMEF"}, {Index: 1, URI: "spotify:track:06QTSGUEgcmKwiEJ0IMPig"}, + {Index: 2, URI: "spotify:track:track2"}, + {Index: 3, URI: "spotify:track:track3"}, }, ExpiredAt: time.Time{}, AllowToControlByOthers: false,