logo
Welcome to our new AbleCommerce forums. As a guest, you may view the information here. To post to this forum, you must have a registered account with us, either as a new user evaluating AbleCommerce or an existing user of the application. For all questions related to the older version of Gold and earlier, please go to AbleCommerce Gold forum. Please use your AbleCommerce username and password to Login. New Registrations are disabled.

Notification

Icon
Error

Options
Go to last post Go to first unread
Joe Payne2  
#1 Posted : Monday, August 23, 2021 7:39:10 PM(UTC)
Joe Payne2

Rank: Advanced Member

Groups: HelpDesk, Developers
Joined: 11/9/2018(UTC)
Posts: 564

Thanks: 122 times
Was thanked: 26 time(s) in 25 post(s)
I've been troubleshooting this thing for hours.

When you use the SEO Settings page to regenerate urls, it fires two async tasks. One for Products, and one for Categories.

Mine is crashing when it hits a category with 4 products and all 4 products have the exact same product name. SQL throws a unique index error on ac_CatalogUrls.

Here's how the code runs:
Hits Copy 1 of product
Sees the url does not already exist
Goes ahead and generates standard url (without a -P123)
Sets the product url
Saves the product, which cascade saves the catalogObject child to create the ac_CatalogUrl record

Hits copy 2 of product
Sees the url does not already exist

That's the problem. This code isn't seeing the url was created and saved by the first copy of the product. And the initial url would be exactly the same because the product name is exactly the same.

Code:

        /// <inheritdoc />
        public CatalogUrl LoadCatalogUrl(string url)
        {
            url = url.ToLowerInvariant();
            ICriteria criteria = NHibernateHelper.CreateCriteria<CatalogUrl>();
            criteria.Add(Restrictions.Eq("Store", AbleContext.Current.Store));
            criteria.Add(Restrictions.Eq("LoweredUrl", url.ToLowerInvariant()));
            IList<CatalogUrl> urls = criteria.List<CatalogUrl>();
            if (urls.Count > 0) return urls[0];
            return null;
        }



This routine keeps returning null for all 4 products. So the calling routines think they're supposed to use the standard url, which is (by then) already created.

So when the CommitTransaction() is fired, SQL tries to write all the records it was told to save but hits a duplicate unique key and throws the exception.

What I've found as the cause is the use of BeginTransaction() inside the AWAIT task routines. If I comment out the Begin/Commit Transaction lines in BOTH the Products routine and Categories routine, the whole thing takes an eternity to run but it correctly identifies duplicated urls and adjusts the urls accordingly.

I can't find a lot about it, but it seems like we've got a problem with using SQL Transactions inside AWAIT async routines. At least in my case, it's not working.

I set up a short test scenario in a default AC904 install, just to see if I could reproduce the problem using the sample data. Just added 4 of the exact same product name to a category. I don't get an error there. That tells me it has something to do with the size of the data of my catalog, 700+ categories and 9,000+ products.

Why, I don't know. But I do know taking out the begin/commit in the routines solves the issue I am having.

Wanna join the discussion?! Login to your AbleCommerce Forums forum account. New Registrations are disabled.

Joe Payne2  
#2 Posted : Tuesday, August 24, 2021 5:18:40 AM(UTC)
Joe Payne2

Rank: Advanced Member

Groups: HelpDesk, Developers
Joined: 11/9/2018(UTC)
Posts: 564

Thanks: 122 times
Was thanked: 26 time(s) in 25 post(s)
Part 2:
Even after leaving the routine run without begin/commit transactions, several hours later it still failed. Just a 500 error, so I can't tell if it's a page timeout or another crash.

I wound up eliminating all the async task/await logic and simply made two calls to the specified routines. And re-activated the begin/commit transaction logic. Whole routine finished without error in about 10 minutes.

Definitely a lot of love is needed here. No UI feedback on errors encountered during the process execution. No UI feedback if the routine fails to complete. No progress bar indicators.

This would be yet another perfect reason to add HangFire to the app. Launch the process, log errors to the Able error log or preferably a physical log file in /App_Data/Logs/, and the UI can easily detect the Hangfire job status.
Users browsing this topic
Guest
Forum Jump  
You cannot post new topics in this forum.
You cannot reply to topics in this forum.
You cannot delete your posts in this forum.
You cannot edit your posts in this forum.
You cannot create polls in this forum.
You cannot vote in polls in this forum.