From 74f8c246605411a802ae788f2ddbae0c2cbb1821 Mon Sep 17 00:00:00 2001 From: Nicklas Ronge Date: Sat, 9 May 2020 17:57:42 +0200 Subject: [PATCH 1/3] - fixed a rate limit issue which was caused by requests not getting marked as finished (#695) --- CHANGELOG.md | 4 ++ .../poe/service/trade-rate-limit.service.ts | 46 ++++++++++++------- .../evaluate-search.component.ts | 16 +++++-- 3 files changed, 46 insertions(+), 20 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 19e44e3a..424fbc2f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,9 @@ # Changelog +## 0.6.28 (2020-05-09) + +- fixed a rate limit issue which was caused by requests not getting marked as finished (#695) + ## 0.6.27 (2020-05-08) - updated rate limiting behavior (#678) diff --git a/src/app/data/poe/service/trade-rate-limit.service.ts b/src/app/data/poe/service/trade-rate-limit.service.ts index 6f94e363..83aa5186 100644 --- a/src/app/data/poe/service/trade-rate-limit.service.ts +++ b/src/app/data/poe/service/trade-rate-limit.service.ts @@ -1,7 +1,7 @@ import { HttpResponse } from '@angular/common/http'; import { Injectable } from '@angular/core'; import { Observable, of, throwError } from 'rxjs'; -import { catchError, delay, flatMap, map, retryWhen } from 'rxjs/operators'; +import { catchError, delay, finalize, flatMap, map, retryWhen } from 'rxjs/operators'; // 1 request // x-rate-limit-ip: 12:4:10,16:12:300 @@ -62,9 +62,10 @@ interface TradeRateLimit { enum TradeRateThrottle { None = 1, - Stale = 2, - Reached = 3, - Limited = 4 + NoRules = 2, + Stale = 3, + Reached = 4, + Limited = 5 } @Injectable({ @@ -82,20 +83,22 @@ export class TradeRateLimitService { switch (reason) { case TradeRateThrottle.Limited: return throwError('limited'); + case TradeRateThrottle.NoRules: case TradeRateThrottle.Reached: case TradeRateThrottle.Stale: return throwError('waiting'); default: const request = this.createRequest(resource); - return getRequest().pipe( + return of(null).pipe( + flatMap(() => getRequest().pipe( + finalize(() => request.finished = Date.now()) + )), map(response => { - request.finished = Date.now(); this.updateRules(resource, response); this.filterRequests(resource); return response.body }), catchError(response => { - request.finished = Date.now(); if (response.status === 429) { this.updateRules(resource, response); } @@ -129,15 +132,20 @@ export class TradeRateLimitService { const { rules, requests, update } = this.getLimit(resource); const inflight = requests.some(request => !request.finished); - if (!inflight) { - return TradeRateThrottle.None; + if (!rules) { + if (!inflight) { + // allow a new request to gather rules + return TradeRateThrottle.None; + } + // request made for gathering rules + // do not allow any further requests + return TradeRateThrottle.NoRules; } - // only allow 1 request until - // > rules are filled - // > rules are fresh again const now = Date.now(); - if (!rules || (now - update) > RULE_FRESH_DURATION) { + if (inflight && (now - update) > RULE_FRESH_DURATION) { + // a request was made and data is stale + // wait for request to be finished before allowing further requests return TradeRateThrottle.Stale; } @@ -173,16 +181,22 @@ export class TradeRateLimitService { private filterRequests(resource: string): void { const limit = this.getLimit(resource); + + const { rules, requests } = limit; + if (!rules) { + return; + } + const now = Date.now(); - limit.requests = limit.requests.filter(request => { + limit.requests = requests.filter(request => { if (!request.finished) { return true; } - return limit.rules.some(rule => { + return rules.some(rule => { const min = now - rule.period * 1000; return request.finished >= min; }); - }) + }); } private updateRules(resource: string, response: HttpResponse): void { diff --git a/src/app/modules/evaluate/component/evaluate-search/evaluate-search.component.ts b/src/app/modules/evaluate/component/evaluate-search/evaluate-search.component.ts index 001dd3b4..f8dfe8cb 100644 --- a/src/app/modules/evaluate/component/evaluate-search/evaluate-search.component.ts +++ b/src/app/modules/evaluate/component/evaluate-search/evaluate-search.component.ts @@ -1,4 +1,4 @@ -import { ChangeDetectionStrategy, Component, EventEmitter, Input, OnInit, Output } from '@angular/core'; +import { ChangeDetectionStrategy, Component, EventEmitter, Input, OnDestroy, OnInit, Output } from '@angular/core'; import { BrowserService, LoggerService } from '@app/service'; import { EvaluateResult } from '@modules/evaluate/type/evaluate.type'; import { ItemSearchAnalyzeResult, ItemSearchAnalyzeService, ItemSearchListing, ItemSearchResult, ItemSearchService } from '@shared/module/poe/service'; @@ -15,8 +15,10 @@ import { EvaluateResultView, EvaluateUserSettings, EVALUATE_QUERY_DEBOUNCE_TIME_ styleUrls: ['./evaluate-search.component.scss'], changeDetection: ChangeDetectionStrategy.OnPush }) -export class EvaluateSearchComponent implements OnInit { +export class EvaluateSearchComponent implements OnInit, OnDestroy { + private searchSubscription: Subscription; private listSubscription: Subscription; + private analyzeSubscription: Subscription; public graph: boolean; @@ -60,6 +62,12 @@ export class EvaluateSearchComponent implements OnInit { } } + public ngOnDestroy(): void { + this.searchSubscription?.unsubscribe(); + this.listSubscription?.unsubscribe(); + this.analyzeSubscription?.unsubscribe(); + } + public onSearchClick(): void { this.initSearch(); } @@ -145,7 +153,7 @@ export class EvaluateSearchComponent implements OnInit { const options: ItemSearchOptions = { ...this.options }; - this.itemSearchService.search(item, options).pipe( + this.searchSubscription = this.itemSearchService.search(item, options).pipe( takeUntil(this.queryItemChange) ).subscribe(search => { this.search$.next(search); @@ -170,7 +178,7 @@ export class EvaluateSearchComponent implements OnInit { private analyze(listings: ItemSearchListing[], currency?: Currency): void { const currencies = currency ? [currency] : this.currencies; - this.itemSearchAnalyzeService.analyze(listings, currencies).pipe( + this.analyzeSubscription = this.itemSearchAnalyzeService.analyze(listings, currencies).pipe( takeUntil(this.queryItemChange) ).subscribe( result => this.result$.next(result), From 97a6350871b939ed234bcbfbae4d022a76f84796 Mon Sep 17 00:00:00 2001 From: Nicklas Ronge Date: Sat, 9 May 2020 20:44:31 +0200 Subject: [PATCH 2/3] - added fetch count at the option menu (#692) --- CHANGELOG.md | 1 + .../evaluate-dialog.component.ts | 12 ++++--- .../evaluate-options.component.html | 27 ++++++++------- .../evaluate-options.component.scss | 7 ++++ .../evaluate-options.component.ts | 33 ++++++++++++++----- .../evaluate-search.component.ts | 4 +-- 6 files changed, 58 insertions(+), 26 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 424fbc2f..c0211104 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,7 @@ ## 0.6.28 (2020-05-09) +- added fetch count at the option menu (#692) - fixed a rate limit issue which was caused by requests not getting marked as finished (#695) ## 0.6.27 (2020-05-08) diff --git a/src/app/modules/evaluate/component/evaluate-dialog/evaluate-dialog.component.ts b/src/app/modules/evaluate/component/evaluate-dialog/evaluate-dialog.component.ts index 8dfb3120..eb4616ee 100644 --- a/src/app/modules/evaluate/component/evaluate-dialog/evaluate-dialog.component.ts +++ b/src/app/modules/evaluate/component/evaluate-dialog/evaluate-dialog.component.ts @@ -6,7 +6,7 @@ import { StashPriceTagType } from '@shared/module/poe/service'; import { CurrencyService } from '@shared/module/poe/service/currency/currency.service'; import { Currency, Item, ItemCategory, ItemRarity, Language } from '@shared/module/poe/type'; import { BehaviorSubject, forkJoin, Observable, Subject } from 'rxjs'; -import { buffer, debounceTime, shareReplay, delay } from 'rxjs/operators'; +import { buffer, debounceTime, delay, shareReplay } from 'rxjs/operators'; import { EvaluateOptions } from '../evaluate-options/evaluate-options.component'; import { EvaluateUserSettings } from '../evaluate-settings/evaluate-settings.component'; @@ -47,12 +47,14 @@ export class EvaluateDialogComponent implements OnInit, AfterViewInit, OnDestroy } public ngOnInit(): void { + const { settings, item } = this.data; this.options = { - indexed: this.data.settings.evaluateQueryIndexedRange, - online: this.data.settings.evaluateQueryOnline, - leagueId: this.data.settings.leagueId + indexed: settings.evaluateQueryIndexedRange, + online: settings.evaluateQueryOnline, + leagueId: settings.leagueId, + fetchCount: settings.evaluateQueryFetchCount }; - const { defaultItem, queryItem } = this.evaluateQueryItemProvider.provide(this.data.item, this.data.settings); + const { defaultItem, queryItem } = this.evaluateQueryItemProvider.provide(item, settings); this.defaultItem = defaultItem; this.queryItem = queryItem; this.currencies$ = this.getCurrencies(); diff --git a/src/app/modules/evaluate/component/evaluate-options/evaluate-options.component.html b/src/app/modules/evaluate/component/evaluate-options/evaluate-options.component.html index 7fb20dd9..faa975e5 100644 --- a/src/app/modules/evaluate/component/evaluate-options/evaluate-options.component.html +++ b/src/app/modules/evaluate/component/evaluate-options/evaluate-options.component.html @@ -9,25 +9,30 @@ {{ leagues[options.leagueId] }} + - - - - wifi - - - - - wifi_off - - + + + {{options.online ? 'wifi' : 'wifi_off'}} + {{ options.indexed }} + + + + + + + + {{ options.fetchCount }} + {{'evaluate.count' | translate}} + + diff --git a/src/app/modules/evaluate/component/evaluate-options/evaluate-options.component.scss b/src/app/modules/evaluate/component/evaluate-options/evaluate-options.component.scss index adf0d077..2b8a959e 100644 --- a/src/app/modules/evaluate/component/evaluate-options/evaluate-options.component.scss +++ b/src/app/modules/evaluate/component/evaluate-options/evaluate-options.component.scss @@ -23,5 +23,12 @@ outline-width: 1px; } } + + .divider{ + border-bottom: 1px solid $light-grey; + width: 50%; + padding-top: 5px; + margin-bottom: 5px; + } } } diff --git a/src/app/modules/evaluate/component/evaluate-options/evaluate-options.component.ts b/src/app/modules/evaluate/component/evaluate-options/evaluate-options.component.ts index 1bc879fe..2bad733b 100644 --- a/src/app/modules/evaluate/component/evaluate-options/evaluate-options.component.ts +++ b/src/app/modules/evaluate/component/evaluate-options/evaluate-options.component.ts @@ -9,6 +9,7 @@ export interface EvaluateOptions { online: boolean; indexed: ItemSearchIndexed; leagueId: string; + fetchCount: number; } type LeagueMap = { @@ -53,11 +54,11 @@ export class EvaluateOptionsComponent implements OnInit { this.optionsChange.emit(this.options); } - public onIndexedWheel(event: WheelEvent): void { + public onLeaguesWheel(event: WheelEvent, leagues: LeagueMap): void { const factor = event.deltaY > 0 ? -1 : 1; - const keys = Object.getOwnPropertyNames(ItemSearchIndexed); + const keys = Object.getOwnPropertyNames(leagues); - let index = keys.findIndex(x => ItemSearchIndexed[x] === this.options.indexed); + let index = keys.findIndex(id => id === this.options.leagueId); index += factor; if (index >= keys.length) { @@ -67,15 +68,15 @@ export class EvaluateOptionsComponent implements OnInit { } const key = keys[index]; - this.options.indexed = ItemSearchIndexed[key]; + this.options.leagueId = key; this.optionsChange.emit(this.options); } - public onLeaguesWheel(event: WheelEvent, leagues: LeagueMap): void { + public onIndexedWheel(event: WheelEvent): void { const factor = event.deltaY > 0 ? -1 : 1; - const keys = Object.getOwnPropertyNames(leagues); + const keys = Object.getOwnPropertyNames(ItemSearchIndexed); - let index = keys.findIndex(id => id === this.options.leagueId); + let index = keys.findIndex(x => ItemSearchIndexed[x] === this.options.indexed); index += factor; if (index >= keys.length) { @@ -85,10 +86,26 @@ export class EvaluateOptionsComponent implements OnInit { } const key = keys[index]; - this.options.leagueId = key; + this.options.indexed = ItemSearchIndexed[key]; this.optionsChange.emit(this.options); } + public onFetchCountWheel(event: WheelEvent): void { + const factor = event.deltaY > 0 ? -1 : 1; + + let fetchCount = this.options.fetchCount + factor * 10; + if (fetchCount > 100) { + fetchCount = 10; + } else if (fetchCount < 10) { + fetchCount = 100; + } + + if (fetchCount !== this.options.fetchCount) { + this.options.fetchCount = fetchCount; + this.optionsChange.emit(this.options); + } + } + public onResetClick(): void { this.resetTrigger.next(); } diff --git a/src/app/modules/evaluate/component/evaluate-search/evaluate-search.component.ts b/src/app/modules/evaluate/component/evaluate-search/evaluate-search.component.ts index f8dfe8cb..22d9589c 100644 --- a/src/app/modules/evaluate/component/evaluate-search/evaluate-search.component.ts +++ b/src/app/modules/evaluate/component/evaluate-search/evaluate-search.component.ts @@ -158,7 +158,7 @@ export class EvaluateSearchComponent implements OnInit, OnDestroy { ).subscribe(search => { this.search$.next(search); if (search.total > 0) { - const count = Math.min(this.settings.evaluateQueryFetchCount, search.total); + const count = Math.min(this.options.fetchCount, search.total); this.count$.next(count); this.list(search); } @@ -166,7 +166,7 @@ export class EvaluateSearchComponent implements OnInit, OnDestroy { } private list(search: ItemSearchResult): void { - this.listSubscription = this.itemSearchService.list(search, this.settings.evaluateQueryFetchCount).pipe( + this.listSubscription = this.itemSearchService.list(search, this.options.fetchCount).pipe( takeUntil(this.queryItemChange) ).subscribe(listings => { this.listings$.next(listings); From 40898fc0a6504d43a70da7970be6aa0fb3d1ad3e Mon Sep 17 00:00:00 2001 From: Nicklas Ronge Date: Sat, 9 May 2020 20:56:31 +0200 Subject: [PATCH 3/3] - 0.6.28 --- README.md | 8 ++++---- package.json | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index d96e7ce6..248142e2 100644 --- a/README.md +++ b/README.md @@ -3,7 +3,7 @@ ![GitHub Release Date](https://img.shields.io/github/release-date/Kyusung4698/PoE-Overlay) Become a Patron -# PoE Overlay 0.6.27 +# PoE Overlay 0.6.28 An Overlay for Path of Exile. The ***core aspect*** is to blend in with the game. Built with Electron and Angular. @@ -74,11 +74,11 @@ These instructions will set you up to run and enjoy the overlay. #### Installing 1. Head over to [Releases](https://github.com/Kyusung4698/PoE-Overlay/releases) and download one of the following files - 1. `poe-overlay-Setup-0.6.27.exe` to install locally. This supports auto update/ auto launch. - 2. `poe-overlay-0.6.27.exe` portable version. This does not support auto update/ auto launch. + 1. `poe-overlay-Setup-0.6.28.exe` to install locally. This supports auto update/ auto launch. + 2. `poe-overlay-0.6.28.exe` portable version. This does not support auto update/ auto launch. 2. Run either of your downloaded file 3. Start Path of Exile -4. Wait until you can see `PoE Overlay 0.6.27` in the bottom left corner +4. Wait until you can see `PoE Overlay 0.6.28` in the bottom left corner 5. Hit `f7` and set `Language` and `League` to meet your game settings #### Shortcuts diff --git a/package.json b/package.json index 5bfb9623..a1ec70b2 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "poe-overlay", - "version": "0.6.27", + "version": "0.6.28", "private": true, "description": "A Overlay for Path of Exile. Built with Electron and Angular.", "main": "main.js",