Esempio n. 1
0
        public static async Task FullUpdatePackagesMetadata()
        {
            Log.WriteInfo(nameof(FullUpdateProcessor), "Doing a full update for packages using metadata requests");

            await using var db = await Database.GetConnectionAsync();

            var subs = db.Query <uint>("SELECT `SubID` FROM `Subs` ORDER BY `SubID` DESC").ToList();

            foreach (var list in subs.Split(IdsPerMetadataRequest))
            {
                do
                {
                    AsyncJobMultiple <SteamApps.PICSProductInfoCallback> job = null;

                    try
                    {
                        job         = Steam.Instance.Apps.PICSGetProductInfo(Enumerable.Empty <SteamApps.PICSRequest>(), list.Select(PICSTokens.NewPackageRequest), true);
                        job.Timeout = TimeSpan.FromMinutes(1);
                        await job;
                        break;
                    }
                    catch (TaskCanceledException)
                    {
                        Log.WriteWarn(nameof(FullUpdateProcessor), $"Package metadata request timed out, job: {job?.JobID}");
                    }
                } while (true);

                do
                {
                    await Task.Delay(500);
                }while (IsBusy());
            }
        }
Esempio n. 2
0
        public void AsyncJobMultipleFinishedOnPredicate()
        {
            SteamClient client = new SteamClient();

            AsyncJobMultiple <Callback> asyncJob = new AsyncJobMultiple <Callback>(client, 123, call => call.IsFinished);
            Task <AsyncJobMultiple <Callback> .ResultSet> asyncTask = asyncJob.ToTask();

            bool jobFinished = asyncJob.AddResult(new Callback {
                JobID = 123, IsFinished = false
            });

            Assert.False(jobFinished, "Async job should not inform that it is finished when completion predicate is false after a result is given");
            Assert.False(asyncTask.IsCompleted, "Async job should not be completed when completion predicate is false");
            Assert.False(asyncTask.IsCanceled, "Async job should not be canceled when completion predicate is false");
            Assert.False(asyncTask.IsFaulted, "Async job should not be faulted when completion predicate is false");

            jobFinished = asyncJob.AddResult(new Callback {
                JobID = 123, IsFinished = true
            });

            Assert.True(jobFinished, "Async job should inform completion when completion predicat is passed after a result is given");
            Assert.True(asyncTask.IsCompleted, "Async job should be completed when completion predicate is true");
            Assert.False(asyncTask.IsCanceled, "Async job should not be canceled when completion predicate is true");
            Assert.False(asyncTask.IsFaulted, "Async job should not be faulted when completion predicate is true");
        }
Esempio n. 3
0
        public async Task AsyncJobMultipleCompletesOnIncompleteResult()
        {
            SteamClient client = new SteamClient();

            client.jobManager.SetTimeoutsEnabled(true);

            AsyncJobMultiple <Callback> asyncJob = new AsyncJobMultiple <Callback>(client, 123, call => call.IsFinished);

            asyncJob.Timeout = TimeSpan.FromSeconds(1);

            Task <AsyncJobMultiple <Callback> .ResultSet> asyncTask = asyncJob.ToTask();

            Callback onlyResult = new Callback {
                JobID = 123, IsFinished = false
            };

            asyncJob.AddResult(onlyResult);

            // adding a result will extend the job's timeout, but we'll cheat here and decrease it
            asyncJob.Timeout = TimeSpan.FromSeconds(1);

            await Task.Delay(TimeSpan.FromSeconds(5));

            Assert.True(asyncTask.IsCompleted, "AsyncJobMultiple should be completed on partial (timed out) result set");
            Assert.False(asyncTask.IsCanceled, "AsyncJobMultiple should not be canceled on partial (timed out) result set");
            Assert.False(asyncTask.IsFaulted, "AsyncJobMultiple should not be faulted on a partial (failed) result set");

            AsyncJobMultiple <Callback> .ResultSet result = asyncTask.Result;

            Assert.False(result.Complete, "ResultSet should be incomplete");
            Assert.False(result.Failed, "ResultSet should not be failed");
            Assert.Equal(result.Results.Count, 1);
            Assert.Contains(onlyResult, result.Results);
        }
Esempio n. 4
0
        public void AsyncJobMultipleCompletesOnIncompleteResultAndFailure()
        {
            SteamClient client = new SteamClient();

            client.jobManager.SetTimeoutsEnabled(true);

            AsyncJobMultiple <Callback> asyncJob = new AsyncJobMultiple <Callback>(client, 123, call => call.IsFinished);

            asyncJob.Timeout = TimeSpan.FromSeconds(1);

            Task <AsyncJobMultiple <Callback> .ResultSet> asyncTask = asyncJob.ToTask();

            Callback onlyResult = new Callback {
                JobID = 123, IsFinished = false
            };

            asyncJob.AddResult(onlyResult);

            asyncJob.SetFailed(dueToRemoteFailure: true);

            Assert.True(asyncTask.IsCompleted, "AsyncJobMultiple should be completed on partial (failed) result set");
            Assert.False(asyncTask.IsCanceled, "AsyncJobMultiple should not be canceled on partial (failed) result set");
            Assert.False(asyncTask.IsFaulted, "AsyncJobMultiple should not be faulted on a partial (failed) result set");

            AsyncJobMultiple <Callback> .ResultSet result = asyncTask.Result;

            Assert.False(result.Complete, "ResultSet should be incomplete");
            Assert.True(result.Failed, "ResultSet should be failed");
            Assert.Equal(result.Results.Count, 1);
            Assert.Contains(onlyResult, result.Results);
        }
Esempio n. 5
0
        public static async Task FullUpdateAppsMetadata(bool fromChangelist = false)
        {
            Log.WriteInfo(nameof(FullUpdateProcessor), "Doing a full update for apps using metadata requests");

            await using var db = await Database.GetConnectionAsync();

            var apps = db.Query <uint>("(SELECT `AppID` FROM `Apps` ORDER BY `AppID` DESC) UNION DISTINCT (SELECT `AppID` FROM `SubsApps` WHERE `Type` = 'app') ORDER BY `AppID` DESC").ToList();

            foreach (var list in apps.Split(fromChangelist ? 1000 : IdsPerMetadataRequest))
            {
                do
                {
                    AsyncJobMultiple <SteamApps.PICSProductInfoCallback> job = null;

                    try
                    {
                        job         = Steam.Instance.Apps.PICSGetProductInfo(list.Select(PICSTokens.NewAppRequest), Enumerable.Empty <SteamApps.PICSRequest>(), true);
                        job.Timeout = TimeSpan.FromMinutes(fromChangelist ? 2 : 1);
                        await job;
                        break;
                    }
                    catch (TaskCanceledException)
                    {
                        Log.WriteWarn(nameof(FullUpdateProcessor), $"Apps metadata request timed out, job: {job?.JobID}");
                    }
                } while (true);

                do
                {
                    await Task.Delay(500);
                }while (IsBusy());
            }
        }
Esempio n. 6
0
        public async Task <KeyValue> GetProductInfo(uint id)
        {
            if (IsLoggedIn == false)
            {
                throw new Exception("Steam not loggin in.");
            }

            try
            {
                SteamApps.PICSProductInfoCallback productInfo;
                var productJob = steamApps.PICSGetProductInfo(id, package: null, onlyPublic: false);

                AsyncJobMultiple <SteamApps.PICSProductInfoCallback> .ResultSet resultSet = await productJob;

                if (resultSet.Complete)
                {
                    productInfo = resultSet.Results.First();
                }
                else
                {
                    productInfo = resultSet.Results.FirstOrDefault(prodCallback => prodCallback.Apps.ContainsKey(id));
                }

                if (productInfo == null)
                {
                    throw new Exception("Failed to get product info for app " + id);
                }

                return(productInfo.Apps[id].KeyValues);
            }
            catch (Exception e)
            {
                throw new Exception("Failed to get product info for app " + id + ". " + e.Message);
            }
        }
Esempio n. 7
0
        public async Task <KeyValue> GetProductInfo(uint id)
        {
            if (!IsConnected)
            {
                var connect = await Connect();

                if (connect != EResult.OK)
                {
                    connect = await Connect();

                    if (connect != EResult.OK)
                    {
                        throw new Exception("Failed to connect to Steam " + connect);
                    }
                }

                isConnected = true;
            }

            if (!IsLoggedIn)
            {
                var logon = await Login();

                if (logon != EResult.OK)
                {
                    throw new Exception("Failed to logon to Steam " + logon);
                }

                isLoggedIn = true;
            }

            try
            {
                SteamApps.PICSProductInfoCallback productInfo;
                var productJob = steamApps.PICSGetProductInfo(id, package: null, onlyPublic: false);

                AsyncJobMultiple <SteamApps.PICSProductInfoCallback> .ResultSet resultSet = await productJob;

                if (resultSet.Complete)
                {
                    productInfo = resultSet.Results.First();
                }
                else
                {
                    productInfo = resultSet.Results.FirstOrDefault(prodCallback => prodCallback.Apps.ContainsKey(id));
                }

                if (productInfo == null)
                {
                    throw new Exception("Failed to get product info for app " + id);
                }

                return(productInfo.Apps[id].KeyValues);
            }
            catch (Exception e)
            {
                throw new Exception("Failed to get product info for app " + id + ". " + e.Message);
            }
        }
Esempio n. 8
0
        public void AsyncJobMultipleThrowsExceptionOnNullCallback()
        {
            SteamClient client = new SteamClient();

            AsyncJobMultiple <Callback> asyncJob = new AsyncJobMultiple <Callback>(client, 123, call => true);

            Assert.Throws <ArgumentNullException>(() => asyncJob.AddResult(null));
        }
Esempio n. 9
0
        public void AsyncJobMultipleClearsOnCompletion()
        {
            SteamClient client = new SteamClient();

            AsyncJobMultiple <Callback> asyncJob = new AsyncJobMultiple <Callback>(client, 123, call => call.IsFinished);

            client.PostCallback(new Callback {
                JobID = 123, IsFinished = true
            });

            Assert.False(client.jobManager.asyncJobs.ContainsKey(asyncJob), "Async job dictionary should not contain jobid key for AsyncJobMultiple on completion");
            Assert.False(client.jobManager.asyncJobs.ContainsKey(123), "Async job dictionary should not contain jobid key (as value type) for AsyncJobMultiple on completion");
        }
Esempio n. 10
0
        public async Task AsyncJobMultipleClearsOnTimeout()
        {
            SteamClient client = new SteamClient();

            client.jobManager.SetTimeoutsEnabled(true);

            AsyncJobMultiple <Callback> asyncJob = new AsyncJobMultiple <Callback>(client, 123, ccall => true);

            asyncJob.Timeout = TimeSpan.FromSeconds(1);

            await Task.Delay(TimeSpan.FromSeconds(5));

            Assert.False(client.jobManager.asyncJobs.ContainsKey(asyncJob), "Async job dictionary should no longer contain jobid key after timeout");
            Assert.False(client.jobManager.asyncJobs.ContainsKey(123), "Async job dictionary should no longer contain jobid key (as value type) after timeout");
        }
Esempio n. 11
0
        public async Task AsyncJobMultipleThrowsFailureExceptionOnFailure()
        {
            SteamClient client = new SteamClient();

            AsyncJobMultiple <Callback> asyncJob = new AsyncJobMultiple <Callback>(client, 123, call => false);
            Task <AsyncJobMultiple <Callback> .ResultSet> asyncTask = asyncJob.ToTask();

            asyncJob.SetFailed(dueToRemoteFailure: true);

            Assert.True(asyncTask.IsCompleted, "AsyncJobMultiple should be completed after job failure");
            Assert.False(asyncTask.IsCanceled, "AsyncJobMultiple should not be canceled after job failure");
            Assert.True(asyncTask.IsFaulted, "AsyncJobMultiple should be faulted after job failure");

            await Assert.ThrowsAsync(typeof(AsyncJobFailedException), async() => await asyncTask);
        }
Esempio n. 12
0
        public void AsyncJobMultipleFinishedOnEmptyPredicate()
        {
            SteamClient client = new SteamClient();

            AsyncJobMultiple <Callback> asyncJob = new AsyncJobMultiple <Callback>(client, 123, call => true);
            Task <AsyncJobMultiple <Callback> .ResultSet> asyncTask = asyncJob.ToTask();

            bool jobFinished = asyncJob.AddResult(new Callback {
                JobID = 123
            });

            Assert.True(jobFinished, "Async job should inform that it is completed when completion predicate is always true and a result is given");
            Assert.True(asyncTask.IsCompleted, "Async job should be completed when empty predicate result is given");
            Assert.False(asyncTask.IsCanceled, "Async job should not be canceled when empty predicate result is given");
            Assert.False(asyncTask.IsFaulted, "Async job should not be faulted when empty predicate result is given");
        }
Esempio n. 13
0
        public async Task AsyncJobMultipleExtendsTimeoutOnMessage()
        {
            SteamClient client = new SteamClient();

            client.jobManager.SetTimeoutsEnabled(true);

            AsyncJobMultiple <Callback> asyncJob = new AsyncJobMultiple <Callback>(client, 123, call => call.IsFinished);

            asyncJob.Timeout = TimeSpan.FromSeconds(5);

            Task <AsyncJobMultiple <Callback> .ResultSet> asyncTask = asyncJob.ToTask();

            // wait 3 seconds before we post any results to this job at all
            await Task.Delay(TimeSpan.FromSeconds(3));

            // we should not be completed or canceled yet
            Assert.False(asyncTask.IsCompleted, "AsyncJobMultiple should not be completed after 3 seconds of 5 second timeout");
            Assert.False(asyncTask.IsCanceled, "AsyncJobMultiple should not be canceled after 3 seconds of 5 second timeout");
            Assert.False(asyncTask.IsFaulted, "AsyncJobMultiple should not be faulted after 3 econds of 5 second timeout");

            // give result 1 of 2
            asyncJob.AddResult(new Callback {
                JobID = 123, IsFinished = false
            });

            // delay for what the original timeout would have been
            await Task.Delay(TimeSpan.FromSeconds(5));

            // we still shouldn't be completed or canceled (timed out)
            Assert.False(asyncTask.IsCompleted, "AsyncJobMultiple should not be completed 5 seconds after a result was added (result should extend timeout)");
            Assert.False(asyncTask.IsCanceled, "AsyncJobMultiple should not be canceled 5 seconds after a result was added (result should extend timeout)");
            Assert.False(asyncTask.IsFaulted, "AsyncJobMultiple should not be faulted 5 seconds aftr a result was added (result should extend timeout)");

            asyncJob.AddResult(new Callback {
                JobID = 123, IsFinished = true
            });

            // we should be completed but not canceled or faulted
            Assert.True(asyncTask.IsCompleted, "AsyncJobMultiple should be completed when final result is added to set");
            Assert.False(asyncTask.IsCanceled, "AsyncJobMultiple should not be canceled when final result is added to set");
            Assert.False(asyncTask.IsFaulted, "AsyncJobMultiple should not be faulted when final result is added to set");
        }
Esempio n. 14
0
        public async Task AsyncJobMultipleTimesout()
        {
            SteamClient client = new SteamClient();

            client.jobManager.SetTimeoutsEnabled(true);

            AsyncJobMultiple <Callback> asyncJob = new AsyncJobMultiple <Callback>(client, 123, call => false);

            asyncJob.Timeout = TimeSpan.FromSeconds(1);

            Task <AsyncJobMultiple <Callback> .ResultSet> asyncTask = asyncJob.ToTask();

            await Task.Delay(TimeSpan.FromSeconds(5));

            Assert.True(asyncTask.IsCompleted, "AsyncJobMultiple should be completed after 5 seconds of a 1 second job timeout");
            Assert.True(asyncTask.IsCanceled, "AsyncJobMultiple should be canceled after 5 seconds of a 1 second job timeout");
            Assert.False(asyncTask.IsFaulted, "AsyncJobMultiple should not be faulted after 5 seconds of a 1 second job timeout");

            await Assert.ThrowsAsync(typeof(TaskCanceledException), async() => await asyncTask);
        }
Esempio n. 15
0
        public async Task <SteamApps.PICSProductInfoCallback.PICSProductInfo> GetAppInfo(uint appID)
        {
            // now request some product info for TF2
            var productJob = steamApps.PICSGetProductInfo(appID, package: null, onlyPublic: false);

            // note that with some requests, Steam can return multiple results, so these jobs don't return the callback object directly, but rather
            // a result set that could contain multiple callback objects if Steam gives us multiple results
            AsyncJobMultiple <SteamApps.PICSProductInfoCallback> .ResultSet resultSet = await productJob;

            SteamApps.PICSProductInfoCallback productInfo;

            if (resultSet.Complete)
            {
                // the request fully completed, we can handle the data
                productInfo = resultSet.Results.First();
            }
            else
            {
                // the request partially completed, but then we timed out. essentially the same as the previous case, but Steam didn't explicitly fail.

                // we still need to check our result set to see if we have our data
                productInfo = resultSet.Results.FirstOrDefault(prodCallback => prodCallback.Apps.ContainsKey(appID));

                if (productInfo != null)
                {
                    // we were lucky and Steam gave us the info we requested before timing out
                }
                else
                {
                    throw new Exception("App Info couldn't be received");
                }
            }

            if (productInfo.Apps.Count == 0)
            {
                throw new Exception("No package found");
            }

            //return productInfo.Apps.FirstOrDefault(prod => prod.Key == appID).Value;
            return(productInfo.Apps[appID]);
        }
Esempio n. 16
0
        public void AsyncJobMultipleContinuesAsynchronously()
        {
            SteamClient client = new SteamClient();

            var asyncJob  = new AsyncJobMultiple <Callback>(client, 123, call => true);
            var asyncTask = asyncJob.ToTask();

            var continuationThreadID = -1;
            var continuation         = asyncTask.ContinueWith(t =>
            {
                continuationThreadID = Environment.CurrentManagedThreadId;
            }, TaskContinuationOptions.ExecuteSynchronously);

            var completionThreadID = Environment.CurrentManagedThreadId;

            asyncJob.AddResult(new Callback {
                JobID = 123
            });

            WaitForTaskWithoutRunningInline(continuation);

            Assert.NotEqual(-1, continuationThreadID);
            Assert.NotEqual(completionThreadID, continuationThreadID);
        }
Esempio n. 17
0
        public async Task AsyncJobMultipleContinuesAsynchronously()
        {
            SteamClient client = new SteamClient();

            var asyncJob  = new AsyncJobMultiple <Callback>(client, 123, call => true);
            var asyncTask = asyncJob.ToTask();

            var continuationThreadID = -1;
            var continuation         = asyncTask.ContinueWith(t =>
            {
                continuationThreadID = Thread.CurrentThread.ManagedThreadId;
            }, TaskContinuationOptions.ExecuteSynchronously);

            var completionThreadID = Thread.CurrentThread.ManagedThreadId;

            asyncJob.AddResult(new Callback {
                JobID = 123
            });

            await continuation;

            Assert.NotEqual(-1, continuationThreadID);
            Assert.NotEqual(completionThreadID, continuationThreadID);
        }
Esempio n. 18
0
        public void AsyncJobMultipleClearsOnCompletion()
        {
            SteamClient client = new SteamClient();

            AsyncJobMultiple<Callback> asyncJob = new AsyncJobMultiple<Callback>( client, 123, call => call.IsFinished );

            client.PostCallback( new Callback { JobID = 123, IsFinished = true } );

            Assert.False( client.jobManager.asyncJobs.ContainsKey( asyncJob ), "Async job dictionary should not contain jobid key for AsyncJobMultiple on completion" );
            Assert.False( client.jobManager.asyncJobs.ContainsKey( 123 ), "Async job dictionary should not contain jobid key (as value type) for AsyncJobMultiple on completion" );
        }
Esempio n. 19
0
        public async void AsyncJobMultipleExtendsTimeoutOnMessage()
        {
            SteamClient client = new SteamClient();
            client.jobManager.SetTimeoutsEnabled( true );

            AsyncJobMultiple<Callback> asyncJob = new AsyncJobMultiple<Callback>( client, 123, call => call.IsFinished );
            asyncJob.Timeout = TimeSpan.FromSeconds( 5 );

            Task<AsyncJobMultiple<Callback>.ResultSet> asyncTask = asyncJob.ToTask();

            // wait 3 seconds before we post any results to this job at all
            await Task.Delay( TimeSpan.FromSeconds( 3 ) );

            // we should not be completed or canceled yet
            Assert.False( asyncTask.IsCompleted, "AsyncJobMultiple should not be completed after 3 seconds of 5 second timeout" );
            Assert.False( asyncTask.IsCanceled, "AsyncJobMultiple should not be canceled after 3 seconds of 5 second timeout" );
            Assert.False( asyncTask.IsFaulted, "AsyncJobMultiple should not be faulted after 3 econds of 5 second timeout" );

            // give result 1 of 2
            asyncJob.AddResult( new Callback { JobID = 123, IsFinished = false } );

            // delay for what the original timeout would have been
            await Task.Delay( TimeSpan.FromSeconds( 5 ) );

            // we still shouldn't be completed or canceled (timed out)
            Assert.False( asyncTask.IsCompleted, "AsyncJobMultiple should not be completed 5 seconds after a result was added (result should extend timeout)" );
            Assert.False( asyncTask.IsCanceled, "AsyncJobMultiple should not be canceled 5 seconds after a result was added (result should extend timeout)" );
            Assert.False( asyncTask.IsFaulted, "AsyncJobMultiple should not be faulted 5 seconds aftr a result was added (result should extend timeout)" );

            asyncJob.AddResult( new Callback { JobID = 123, IsFinished = true } );

            // we should be completed but not canceled or faulted
            Assert.True( asyncTask.IsCompleted, "AsyncJobMultiple should be completed when final result is added to set" );
            Assert.False( asyncTask.IsCanceled, "AsyncJobMultiple should not be canceled when final result is added to set" );
            Assert.False( asyncTask.IsFaulted, "AsyncJobMultiple should not be faulted when final result is added to set" );
        }
        async Task <IEnumerable <IDeal> > IScraper.Scrape(CancellationToken token)
        {
            List <IDeal> deals = new List <IDeal>();

            List <long> appIds = await GetModifiedGames(token);

            if (appIds == null)
            {
                logger.Warn("Null returned from GetModifiedGames");
                return(new List <IDeal>());
            }

            logger.Info("Found {count} modified games", appIds.Count);

            Dictionary <uint, int> filteredAppIds = await FilterAppIds(appIds, token);

            BaseDeals packageData = await CreateBaseDeals(filteredAppIds);

            foreach (PackageKeys package in packageData.Packages)
            {
                await Task.Delay(2000, token);

                logger.Info($"Querying AppId: {package.FilteredAppId}; SubId: {package.PackageId}");
                AsyncJobMultiple <SteamApps.PICSProductInfoCallback> .ResultSet result =
                    await apps.PICSGetProductInfo(package.FilteredAppId, package.PackageId);

                if (result.Failed || result.Results == null || result.Results.Count == 0)
                {
                    continue;
                }

                foreach (SteamApps.PICSProductInfoCallback callback in result.Results)
                {
                    if (!callback.Packages.TryGetValue(package.PackageId, out SteamApps.PICSProductInfoCallback.PICSProductInfo productInfo))
                    {
                        continue;
                    }

                    Deal deal = packageData.IdToDeal[package.FilteredAppId];

                    string?startTime = productInfo.KeyValues["extended"]["starttime"].Value;
                    if (!string.IsNullOrEmpty(startTime))
                    {
                        deal.Start = DateTimeOffset.FromUnixTimeSeconds(long.Parse(startTime)).UtcDateTime;
                    }

                    string?expiryTime = productInfo.KeyValues["extended"]["expirytime"].Value;
                    if (!string.IsNullOrEmpty(expiryTime))
                    {
                        deal.End = DateTimeOffset.FromUnixTimeSeconds(long.Parse(expiryTime)).UtcDateTime;
                    }
                    else
                    {
                        logger.Info("We're ignoring deals without end date for now");
                        continue;
                    }

                    logger.Info("Found date info for deal, finalizing");
                    deals.Add(deal);
                    break;
                }
            }

            return(deals);
        }
Esempio n. 21
0
        public async void AsyncJobMultipleTimesout()
        {
            SteamClient client = new SteamClient();
            client.jobManager.SetTimeoutsEnabled( true );

            AsyncJobMultiple<Callback> asyncJob = new AsyncJobMultiple<Callback>( client, 123, call => false );
            asyncJob.Timeout = TimeSpan.FromSeconds( 1 );

            Task<AsyncJobMultiple<Callback>.ResultSet> asyncTask = asyncJob.ToTask();

            await Task.Delay( TimeSpan.FromSeconds( 5 ) );

            Assert.True( asyncTask.IsCompleted, "AsyncJobMultiple should be completed after 5 seconds of a 1 second job timeout" );
            Assert.True( asyncTask.IsCanceled, "AsyncJobMultiple should be canceled after 5 seconds of a 1 second job timeout" );
            Assert.False( asyncTask.IsFaulted, "AsyncJobMultiple should not be faulted after 5 seconds of a 1 second job timeout" );

            await Assert.ThrowsAsync( typeof( TaskCanceledException ), async () => await asyncTask );
        }
Esempio n. 22
0
        public void AsyncJobMultipleCompletesOnIncompleteResultAndFailure()
        {
            SteamClient client = new SteamClient();
            client.jobManager.SetTimeoutsEnabled( true );

            AsyncJobMultiple<Callback> asyncJob = new AsyncJobMultiple<Callback>( client, 123, call => call.IsFinished );
            asyncJob.Timeout = TimeSpan.FromSeconds( 1 );

            Task<AsyncJobMultiple<Callback>.ResultSet> asyncTask = asyncJob.ToTask();

            Callback onlyResult = new Callback { JobID = 123, IsFinished = false };

            asyncJob.AddResult( onlyResult );

            asyncJob.SetFailed( dueToRemoteFailure: true );

            Assert.True( asyncTask.IsCompleted, "AsyncJobMultiple should be completed on partial (failed) result set" );
            Assert.False( asyncTask.IsCanceled, "AsyncJobMultiple should not be canceled on partial (failed) result set" );
            Assert.False( asyncTask.IsFaulted, "AsyncJobMultiple should not be faulted on a partial (failed) result set" );

            AsyncJobMultiple<Callback>.ResultSet result = asyncTask.Result;

            Assert.False( result.Complete, "ResultSet should be incomplete" );
            Assert.True( result.Failed, "ResultSet should be failed" );
            Assert.Equal( result.Results.Count, 1 );
            Assert.Contains( onlyResult, result.Results );
        }
Esempio n. 23
0
        public async void AsyncJobMultipleCompletesOnIncompleteResult()
        {
            SteamClient client = new SteamClient();
            client.jobManager.SetTimeoutsEnabled( true );

            AsyncJobMultiple<Callback> asyncJob = new AsyncJobMultiple<Callback>( client, 123, call => call.IsFinished );
            asyncJob.Timeout = TimeSpan.FromSeconds( 1 );

            Task<AsyncJobMultiple<Callback>.ResultSet> asyncTask = asyncJob.ToTask();

            Callback onlyResult = new Callback { JobID = 123, IsFinished = false };

            asyncJob.AddResult( onlyResult );

            // adding a result will extend the job's timeout, but we'll cheat here and decrease it
            asyncJob.Timeout = TimeSpan.FromSeconds( 1 );

            await Task.Delay( TimeSpan.FromSeconds( 5 ) );

            Assert.True( asyncTask.IsCompleted, "AsyncJobMultiple should be completed on partial (timed out) result set" );
            Assert.False( asyncTask.IsCanceled, "AsyncJobMultiple should not be canceled on partial (timed out) result set" );
            Assert.False( asyncTask.IsFaulted, "AsyncJobMultiple should not be faulted on a partial (failed) result set" );

            AsyncJobMultiple<Callback>.ResultSet result = asyncTask.Result;

            Assert.False( result.Complete, "ResultSet should be incomplete" );
            Assert.False( result.Failed, "ResultSet should not be failed" );
            Assert.Equal( result.Results.Count, 1 );
            Assert.Contains( onlyResult, result.Results );
        }
Esempio n. 24
0
        public async void AsyncJobMultipleThrowsFailureExceptionOnFailure()
        {
            SteamClient client = new SteamClient();

            AsyncJobMultiple<Callback> asyncJob = new AsyncJobMultiple<Callback>( client, 123, call => false );
            Task<AsyncJobMultiple<Callback>.ResultSet> asyncTask = asyncJob.ToTask();

            asyncJob.SetFailed( dueToRemoteFailure: true );

            Assert.True( asyncTask.IsCompleted, "AsyncJobMultiple should be completed after job failure" );
            Assert.False( asyncTask.IsCanceled, "AsyncJobMultiple should not be canceled after job failure" );
            Assert.True( asyncTask.IsFaulted, "AsyncJobMultiple should be faulted after job failure" );

            await Assert.ThrowsAsync( typeof( AsyncJobFailedException ), async () => await asyncTask );
        }
Esempio n. 25
0
        public void AsyncJobMultipleThrowsExceptionOnNullCallback()
        {
            SteamClient client = new SteamClient();

            AsyncJobMultiple<Callback> asyncJob = new AsyncJobMultiple<Callback>( client, 123, call => true );

            Assert.Throws<ArgumentNullException>( () => asyncJob.AddResult( null ) );
        }
Esempio n. 26
0
        public async Task <KeyValue> GetProductInfo(uint id)
        {
            if (!IsConnected)
            {
                var connect = await Connect();

                if (connect != EResult.OK)
                {
                    connect = await Connect();

                    if (connect != EResult.OK)
                    {
                        throw new Exception("Failed to connect to Steam " + connect);
                    }
                }

                isConnected = true;
            }

            if (!IsLoggedIn)
            {
                var logon = await Login();

                if (logon != EResult.OK)
                {
                    throw new Exception("Failed to logon to Steam " + logon);
                }

                isLoggedIn = true;
            }

            try
            {
                SteamApps.PICSProductInfoCallback productInfo;
                AsyncJobMultiple <SteamApps.PICSProductInfoCallback> .ResultSet resultSet = null;
                var productJob = steamApps.PICSGetProductInfo(id, package: null, onlyPublic: false);

                // Workardound for rare case where PICSGetProductInfo would get stuck if there's some issue with computer's network.
                // For example if PC is woken up from sleep.
                var tsk = productJob.ToTask();
                if (tsk.Wait(10000))
                {
                    resultSet = tsk.Result;
                }
                else
                {
                    throw new Exception("Failed to get product info for app (timeout) " + id);
                }

                if (resultSet.Complete)
                {
                    productInfo = resultSet.Results.First();
                }
                else
                {
                    productInfo = resultSet.Results.FirstOrDefault(prodCallback => prodCallback.Apps.ContainsKey(id));
                }

                if (productInfo == null)
                {
                    throw new Exception("Failed to get product info for app " + id);
                }

                return(productInfo.Apps[id].KeyValues);
            }
            catch (Exception e)
            {
                throw new Exception("Failed to get product info for app " + id + ". " + e.Message);
            }
        }
Esempio n. 27
0
        private async void OnLoggedOn(SteamUser.LoggedOnCallback callback)
        {
            if (callback.Result != EResult.OK)
            {
                if (callback.Result == EResult.AccountLogonDenied)
                {
                    // if we recieve AccountLogonDenied or one of it's flavors (AccountLogonDeniedNoMailSent, etc)
                    // then the account we're logging into is SteamGuard protected
                    // see sample 5 for how SteamGuard can be handled

                    _logger.LogWarning("Unable to logon to Steam: This account is SteamGuard protected.");
                    return;
                }

                _logger.LogError("Unable to logon to Steam: {0} / {1}", callback.Result, callback.ExtendedResult);

                return;
            }

            // in this sample, we'll simply do a few async requests to acquire information about appid 440 (Team Fortress 2)

            // first, we'll request a depot decryption key for TF2's client/server shared depot (441)
            var depotJob = steamApps.GetDepotDecryptionKey(depotid: 441, appid: 440);

            // at this point, this request is now in-flight to the steam server, so we'll use te async/await pattern to wait for a response
            // the await pattern allows this code to resume once the Steam servers have replied to the request.
            // if Steam does not reply to the request in a timely fashion (controlled by the `Timeout` field on the AsyncJob object), the underlying
            // task for this job will be cancelled, and TaskCanceledException will be thrown.
            // additionally, if Steam encounters a remote failure and is unable to process your request, the job will be faulted and an AsyncJobFailedException
            // will be thrown.
            SteamApps.DepotKeyCallback depotKey = await depotJob;

            if (depotKey.Result == EResult.OK)
            {
                _logger.LogDebug($"Got our depot key: {BitConverter.ToString(depotKey.DepotKey)}");
            }
            else
            {
                _logger.LogDebug("Unable to request depot key!");
            }

            // now request some product info for TF2
            var productJob = steamApps.PICSGetProductInfo(440, package: null);

            // note that with some requests, Steam can return multiple results, so these jobs don't return the callback object directly, but rather
            // a result set that could contain multiple callback objects if Steam gives us multiple results
            AsyncJobMultiple <SteamApps.PICSProductInfoCallback> .ResultSet resultSet = await productJob;

            if (resultSet.Complete)
            {
                // the request fully completed, we can handle the data
                SteamApps.PICSProductInfoCallback productInfo = resultSet.Results.First();

                // ... do something with our product info
            }
            else if (resultSet.Failed)
            {
                // the request partially completed, and then Steam encountered a remote failure. for async jobs with only a single result (such as
                // GetDepotDecryptionKey), this would normally throw an AsyncJobFailedException. but since Steam had given us a partial set of callbacks
                // we get to decide what to do with the data

                // keep in mind that if Steam immediately fails to provide any data, or times out while waiting for the first result, an
                // AsyncJobFailedException or TaskCanceledException will be thrown

                // the result set might not have our data, so we need to test to see if we have results for our request
                SteamApps.PICSProductInfoCallback productInfo = resultSet.Results.FirstOrDefault(prodCallback => prodCallback.Apps.ContainsKey(440));

                if (productInfo != null)
                {
                    // we were lucky and Steam gave us the info we requested before failing
                }
                else
                {
                    // bad luck
                }
            }
            else
            {
                // the request partially completed, but then we timed out. essentially the same as the previous case, but Steam didn't explicitly fail.

                // we still need to check our result set to see if we have our data
                SteamApps.PICSProductInfoCallback productInfo = resultSet.Results.FirstOrDefault(prodCallback => prodCallback.Apps.ContainsKey(440));

                if (productInfo != null)
                {
                    // we were lucky and Steam gave us the info we requested before timing out
                }
                else
                {
                    // bad luck
                }
            }

            // lastly, if you're unable to use the async/await pattern (older VS/compiler, etc) you can still directly access the TPL Task associated
            // with the async job by calling `ToTask()`
            var depotTask = steamApps.GetDepotDecryptionKey(depotid: 441, appid: 440).ToTask();

            // set up a continuation for when this task completes
            var ignored = depotTask.ContinueWith(task =>
            {
                depotKey = task.Result;

                // do something with the depot key

                // we're finished with this sample, drop out of the callback loop
            }, TaskContinuationOptions.OnlyOnRanToCompletion);
        }
Esempio n. 28
0
        public async void AsyncJobMultipleClearsOnTimeout()
        {
            SteamClient client = new SteamClient();
            client.jobManager.SetTimeoutsEnabled( true );

            AsyncJobMultiple<Callback> asyncJob = new AsyncJobMultiple<Callback>( client, 123, ccall => true );
            asyncJob.Timeout = TimeSpan.FromSeconds( 1 );

            await Task.Delay( TimeSpan.FromSeconds( 5 ) );

            Assert.False( client.jobManager.asyncJobs.ContainsKey( asyncJob ), "Async job dictionary should no longer contain jobid key after timeout" );
            Assert.False( client.jobManager.asyncJobs.ContainsKey( 123 ), "Async job dictionary should no longer contain jobid key (as value type) after timeout" );
        }
Esempio n. 29
0
        public void AsyncJobMultipleFinishedOnEmptyPredicate()
        {
            SteamClient client = new SteamClient();

            AsyncJobMultiple<Callback> asyncJob = new AsyncJobMultiple<Callback>( client, 123, call => true );
            Task<AsyncJobMultiple<Callback>.ResultSet> asyncTask = asyncJob.ToTask();

            bool jobFinished = asyncJob.AddResult( new Callback { JobID = 123 } );

            Assert.True( jobFinished, "Async job should inform that it is completed when completion predicate is always true and a result is given" );
            Assert.True( asyncTask.IsCompleted, "Async job should be completed when empty predicate result is given" );
            Assert.False( asyncTask.IsCanceled, "Async job should not be canceled when empty predicate result is given" );
            Assert.False( asyncTask.IsFaulted, "Async job should not be faulted when empty predicate result is given" );
        }
Esempio n. 30
0
        public void AsyncJobMultipleFinishedOnPredicate()
        {
            SteamClient client = new SteamClient();

            AsyncJobMultiple<Callback> asyncJob = new AsyncJobMultiple<Callback>( client, 123, call => call.IsFinished );
            Task<AsyncJobMultiple<Callback>.ResultSet> asyncTask = asyncJob.ToTask();

            bool jobFinished = asyncJob.AddResult( new Callback { JobID = 123, IsFinished = false } );

            Assert.False( jobFinished, "Async job should not inform that it is finished when completion predicate is false after a result is given" );
            Assert.False( asyncTask.IsCompleted, "Async job should not be completed when completion predicate is false" );
            Assert.False( asyncTask.IsCanceled, "Async job should not be canceled when completion predicate is false" );
            Assert.False( asyncTask.IsFaulted, "Async job should not be faulted when completion predicate is false" );

            jobFinished = asyncJob.AddResult( new Callback { JobID = 123, IsFinished = true } );

            Assert.True( jobFinished, "Async job should inform completion when completion predicat is passed after a result is given" );
            Assert.True( asyncTask.IsCompleted, "Async job should be completed when completion predicate is true" );
            Assert.False( asyncTask.IsCanceled, "Async job should not be canceled when completion predicate is true" );
            Assert.False( asyncTask.IsFaulted, "Async job should not be faulted when completion predicate is true" );
        }