From 336b91c872cff39dcb678d17dd6cda665138f957 Mon Sep 17 00:00:00 2001 From: DebaucheryLibrarian Date: Wed, 17 Mar 2021 02:09:34 +0100 Subject: [PATCH] Refactored http timeout handling. --- assets/components/releases/release.vue | 64 +++++++++++++++++++++++++- assets/js/fragments.js | 15 ++++++ assets/js/releases/actions.js | 8 +++- assets/js/stashes/actions.js | 10 ++++ assets/js/users/actions.js | 44 ++---------------- migrations/20190325001339_releases.js | 1 - src/app.js | 2 +- src/stashes.js | 28 +++++++---- src/utils/http.js | 47 +++++++++++-------- 9 files changed, 147 insertions(+), 72 deletions(-) diff --git a/assets/components/releases/release.vue b/assets/components/releases/release.vue index d8d4594c..4e857ef2 100644 --- a/assets/components/releases/release.vue +++ b/assets/components/releases/release.vue @@ -50,6 +50,20 @@ icon="question2" /> + + + +
@@ -223,7 +237,7 @@ import Actor from '../actors/tile.vue'; import Releases from './releases.vue'; import Scroll from '../scroll/scroll.vue'; -async function fetchRelease() { +async function fetchRelease(scroll = true) { if (this.$route.name === 'scene') { this.release = await this.$store.dispatch('fetchReleaseById', this.$route.params.releaseId); } @@ -232,11 +246,37 @@ async function fetchRelease() { this.release = await this.$store.dispatch('fetchMovieById', this.$route.params.releaseId); } - if (this.$refs.content) { + if (scroll && this.$refs.content) { this.$refs.content.scrollTop = 0; } } +async function stashScene() { + this.$store.dispatch('stashScene', { + sceneId: this.release.id, + stashId: this.$store.getters.favorites.id, + }); + + this.fetchRelease(false); +} + +async function unstashScene() { + this.$store.dispatch('unstashScene', { + sceneId: this.release.id, + stashId: this.$store.getters.favorites.id, + }); + + this.fetchRelease(false); +} + +function me() { + return this.$store.state.auth.user; +} + +function isStashed() { + return this.release.stashes?.length > 0; +} + function bannerBackground() { return (this.release.poster && this.getBgPath(this.release.poster, 'thumbnail')) || (this.release.covers.length > 0 && this.getBgPath(this.release.covers[0], 'thumbnail')); @@ -271,6 +311,8 @@ export default { computed: { pageTitle, bannerBackground, + isStashed, + me, showAlbum, }, watch: { @@ -279,6 +321,8 @@ export default { mounted: fetchRelease, methods: { fetchRelease, + stashScene, + unstashScene, }, }; @@ -353,6 +397,22 @@ export default { color: var(--shadow); } +.stash.icon { + width: 1.5rem; + height: 1.5rem; + padding: 0 1rem; + fill: var(--darken); + + &.stashed { + fill: var(--primary); + } + + &:hover { + fill: var(--primary); + cursor: pointer; + } +} + .album-toggle { height: fit-content; display: inline-flex; diff --git a/assets/js/fragments.js b/assets/js/fragments.js index d4e6a0e5..ce88777a 100644 --- a/assets/js/fragments.js +++ b/assets/js/fragments.js @@ -346,6 +346,21 @@ const releaseFragment = ` } } } + stashes: stashesScenesBySceneId( + filter: { + stash: { + userId: { + equalTo: $userId + } + } + } + ) @include(if: $hasAuth) { + stash { + id + name + slug + } + } } `; diff --git a/assets/js/releases/actions.js b/assets/js/releases/actions.js index 384d57fc..b5d06ff1 100644 --- a/assets/js/releases/actions.js +++ b/assets/js/releases/actions.js @@ -37,11 +37,17 @@ function initReleasesActions(store, router) { // const release = await get(`/releases/${releaseId}`); const { release } = await graphql(` - query Release($releaseId:Int!) { + query Release( + $releaseId: Int! + $hasAuth: Boolean! + $userId: Int + ) { ${releaseFragment} } `, { releaseId: Number(releaseId), + hasAuth: !!store.state.auth.user, + userId: store.state.auth.user?.id, }); if (!release) { diff --git a/assets/js/stashes/actions.js b/assets/js/stashes/actions.js index 0188d8a1..4d3dbee4 100644 --- a/assets/js/stashes/actions.js +++ b/assets/js/stashes/actions.js @@ -9,9 +9,19 @@ function initStashesActions(_store, _router) { await del(`/stashes/${stashId}/actors/${actorId}`); } + async function stashScene(context, { sceneId, stashId }) { + await post(`/stashes/${stashId}/scenes`, { sceneId }); + } + + async function unstashScene(context, { sceneId, stashId }) { + await del(`/stashes/${stashId}/scenes/${sceneId}`); + } + return { stashActor, + stashScene, unstashActor, + unstashScene, }; } diff --git a/assets/js/users/actions.js b/assets/js/users/actions.js index c62f236d..fa3a074e 100644 --- a/assets/js/users/actions.js +++ b/assets/js/users/actions.js @@ -1,4 +1,6 @@ import { graphql } from '../api'; +import { releaseFields } from '../fragments'; +import { curateUser } from '../curate'; function initUsersActions(_store, _router) { async function fetchUser(context, username) { @@ -43,45 +45,7 @@ function initUsersActions(_store, _router) { scenes: stashesScenes { comment scene { - id - title - slug - url - date - actors: releasesActors { - actor { - id - name - slug - } - } - tags: releasesTags { - tag { - id - name - slug - } - } - entity { - id - name - slug - independent - parent { - id - name - slug - independent - } - } - poster: releasesPosterByReleaseId { - media { - path - thumbnail - lazy - isS3 - } - } + ${releaseFields} } } } @@ -91,7 +55,7 @@ function initUsersActions(_store, _router) { username, }); - return user; + return curateUser(user); } return { diff --git a/migrations/20190325001339_releases.js b/migrations/20190325001339_releases.js index 60b19005..6de2caba 100644 --- a/migrations/20190325001339_releases.js +++ b/migrations/20190325001339_releases.js @@ -1328,7 +1328,6 @@ exports.up = knex => Promise.resolve() )); `, { visitor: knex.raw(config.database.query.user), - password: knex.raw(config.database.query.password), }); }) // VIEWS AND COMMENTS diff --git a/src/app.js b/src/app.js index 82fef6f1..785d8da7 100644 --- a/src/app.js +++ b/src/app.js @@ -21,7 +21,7 @@ function logActive() { setTimeout(() => { log(); logActive(); - }, 600000); + }, argv.logActive || 60000); } async function init() { diff --git a/src/stashes.js b/src/stashes.js index 47bb4e79..a61fffdc 100644 --- a/src/stashes.js +++ b/src/stashes.js @@ -48,19 +48,31 @@ async function stashScene(sceneId, stashId, sessionUser) { await knex('stashes_scenes') .insert({ stash_id: stash.id, - actor_id: sceneId, + scene_id: sceneId, }); } async function unstashActor(actorId, stashId, sessionUser) { await knex - .from('stashes_actors') - .whereIn('stashes_actors.id', knex('stashes_actors') - .select('stashes_actors.id') + .from('stashes_actors AS deletable') + .where('deletable.actor_id', actorId) + .where('deletable.stash_id', stashId) + .whereExists(knex('stashes_actors') // verify user owns this stash .leftJoin('stashes', 'stashes.id', 'stashes_actors.stash_id') - .where('stashes.user_id', sessionUser.id) // verify user owns this stash - .where('stashes_actors.actor_id', actorId) - .where('stashes_actors.stash_id', stashId)) + .where('stashes_actors.stash_id', knex.raw('deletable.stash_id')) + .where('stashes.user_id', sessionUser.id)) + .delete(); +} + +async function unstashScene(sceneId, stashId, sessionUser) { + await knex + .from('stashes_scenes AS deletable') + .where('deletable.scene_id', sceneId) + .where('deletable.stash_id', stashId) + .whereExists(knex('stashes_scenes') // verify user owns this stash + .leftJoin('stashes', 'stashes.id', 'stashes_scenes.stash_id') + .where('stashes_scenes.stash_id', knex.raw('deletable.stash_id')) + .where('stashes.user_id', sessionUser.id)) .delete(); } @@ -68,6 +80,6 @@ module.exports = { curateStash, stashActor, stashScene, - // unstashScene, + unstashScene, unstashActor, }; diff --git a/src/utils/http.js b/src/utils/http.js index 4573f833..99856ffc 100644 --- a/src/utils/http.js +++ b/src/utils/http.js @@ -80,20 +80,9 @@ function getLimiter(options = {}, url) { return limiters[interval][concurrency]; } -async function request(method = 'get', url, body, requestOptions = {}, limiter, timeout) { +async function request(method = 'get', url, body, requestOptions = {}, limiter) { const http = requestOptions.session || bhttp; - - const options = { - ...defaultOptions, - ...requestOptions, - headers: { - ...defaultOptions.headers, - ...requestOptions.headers, - }, - responseTimeout: requestOptions.responseTimeout || requestOptions.timeout || defaultOptions.timeout, - stream: !!requestOptions.destination, - session: null, - }; + const options = requestOptions; const withProxy = useProxy(url); @@ -107,8 +96,10 @@ async function request(method = 'get', url, body, requestOptions = {}, limiter, ? http[method](url, body, options) : http[method](url, options)); - timeout.cancel(); + return res; +} +async function finalizeResult(res, options) { if (options.destination) { // res.on('progress', (bytes, totalBytes) => logger.silly(`Downloaded ${Math.round((bytes / totalBytes) * 100)}% of ${url}`)); @@ -140,21 +131,39 @@ async function request(method = 'get', url, body, requestOptions = {}, limiter, function getTimeout(options, url) { return new Promise((resolve, reject, onCancel) => { - const timeoutId = setTimeout(() => { + const timeout = setTimeout(() => { reject(new Error(`URL ${url} timed out`)); }, (options?.timeout || defaultOptions.timeout) + 10000); - onCancel(() => clearTimeout(timeoutId)); + onCancel(() => { + clearTimeout(timeout); + }); }); } -async function scheduleRequest(method = 'get', url, body, options) { +async function scheduleRequest(method = 'get', url, body, requestOptions = {}) { + const options = { + ...defaultOptions, + ...requestOptions, + headers: { + ...defaultOptions.headers, + ...requestOptions.headers, + }, + responseTimeout: requestOptions.responseTimeout || requestOptions.timeout || defaultOptions.timeout, + stream: !!requestOptions.destination, + session: null, + }; + const limiter = getLimiter(options, url); const timeout = getTimeout(options, url); - const result = await limiter.schedule(() => Promise.race([request(method, url, body, options, limiter, timeout), timeout])); + const result = await limiter.schedule(async () => Promise.race([request(method, url, body, options, limiter), timeout])); - return result; + timeout.cancel(); + + const curatedResult = await finalizeResult(result, options); + + return curatedResult; } async function get(url, options) {