Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix outputcache FileProvider invalid datetime culture format #4915

Merged
merged 12 commits into from
Jan 18, 2022

Conversation

thienvc
Copy link
Contributor

@thienvc thienvc commented Nov 21, 2021

Fix outputcache FileProvider invalid datetime culture format

@bdukes bdukes linked an issue Nov 22, 2021 that may be closed by this pull request
@bdukes
Copy link
Contributor

bdukes commented Nov 22, 2021

Can you clarify what issue you're seeing, how to reproduce and validate that this fixes the issue? It looks like there are maybe two or three different fixes in this PR, is that right?

@thienvc
Copy link
Contributor Author

thienvc commented Nov 22, 2021

Can you clarify what issue you're seeing, how to reproduce and validate that this fixes the issue? It looks like there are maybe two or three different fixes in this PR, is that right?

DateTime.UtcNow.Add(duration).ToString() sometimes return localized date style like "2021-11-21 9:44:90 CH".
When the PureCache Scheduler reads the Expiry Date from the .attrib.resources file which cannot be parsed because the scheduler runs NeuturalCulture.
So it must be clear InvariantCulture ToString(CultureInfo.InvariantCulture)
See more similar situation in ModuleCache FileProvider:

File.WriteAllLines(attribFile, new[] { DateTime.UtcNow.Add(duration).ToString(CultureInfo.InvariantCulture) });

@thienvc
Copy link
Contributor Author

thienvc commented Nov 22, 2021

In addition, during debugging, I encountered an annoying situation when both the cache files of the Module and Page were in the same Cache\Pages folder, which was very difficult to distinguish. I've put together a PR that separates the Module's Cache folder into a separate folder called Cache\Modules, hoping for approval.
cacheFolder = string.Concat(homeDirectoryMapPath, "Cache\\Modules\\");

cacheFolder = string.Concat(homeDirectoryMapPath, "Cache\\Modules\\");

@thienvc
Copy link
Contributor Author

thienvc commented Nov 22, 2021

It looks like there are maybe two or three different fixes in this PR, is that right?

No, just because PR1 I forgot to delete some meaningless variables I added for debugging so I don't know how to recover so I push PR2 again.

Variables I added but forgot to remove:

var currentCulture = CultureInfo.CurrentCulture.DateTimeFormat;
var currentCultureX = CultureInfo.DefaultThreadCurrentCulture.DateTimeFormat;
var datetimeUtc = DateTime.UtcNow.Add(duration).ToString(CultureInfo.InvariantCulture);
var datetime1 = DateTime.UtcNow.Add(duration).ToString();
var datetime2 = DateTime.UtcNow.Add(duration).ToString();

Copy link
Contributor

@bdukes bdukes left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good to me, thanks!

@thienvc
Copy link
Contributor Author

thienvc commented Nov 23, 2021

I've built and tested on the actual running environment, it runs very well, it's faster
In addition, in the Database cache mechanism, there is also a small error that when inserting content into the OutputCache table, the PrimaryKey is not checked, leading to the Dublicate Primary Key error.
I don't know if I should pull PR to fix this error? This error does not cause a system crash, but Log Viewer is reported to be full
SQL here, Always insert data without checking PrimaryKey:

BEGIN
INSERT INTO {databaseOwner}{objectQualifier}OutputCache
( ItemId,
CacheKey,
Data,
Expiration
) VALUES
( @ItemId,
@CacheKey,
@Data,
@Expiration
)
END

I fixed on my production site

BEGIN

	IF NOT EXISTS (SELECT CacheKey from dbo.OutputCache where CacheKey = @CacheKey)
		begin
		    INSERT INTO dbo.OutputCache
				(ItemId, 
				CacheKey, 
				Data, 
				Expiration
				) VALUES 
				(@ItemId, 
				@CacheKey, 
				@Data, 
				@Expiration
				)
		end
	ELSE UPDATE dbo.OutputCache Set Data = @Data, Expiration = @Expiration Where CacheKey = @CacheKey
END

@bdukes I do not know should pull this PR? and where to fix?

@bdukes bdukes changed the base branch from master to develop November 23, 2021 15:38
@bdukes
Copy link
Contributor

bdukes commented Nov 23, 2021

Yes, a PR for that would be welcome. You'd need to introduce a new SQL file, 09.10.03.SqlDataProvider with the code to update that stored procedure.

Also, I've updated this PR to target the develop branch (the master branch is only updated when new versions are released). Can you rebase your changes on develop? It may be easier to start a new branch from develop just for this PR and re-submit from that branch.

Thanks!

@bdukes bdukes added this to the 9.10.3 milestone Nov 23, 2021
@sleupold
Copy link
Contributor

I suggest using a SQL merge statement instead for better performance
MERGE INTO {databaseOwner}[{objectQualifier}outputCache] T
USING (SELECT @itemid as ItemID, @Cachekey as CacheKey, ...) S on T.cacheKey = S.CacheKey
WHEN NOT EXIST THEN Insert (ItemID, CacheKey, ...) VALUES S.ItemID, S.CacheKey, ...)

@mitchelsellers
Copy link
Contributor

mitchelsellers commented Nov 24, 2021

If adding the SQL fix I believe that the structure outlined by @thienvc is appropriate, per the following guidance from Microsoft.

Performance Tip: The conditional behavior described for the MERGE statement works best when the two tables have a complex mixture of matching characteristics. For example, inserting a row if it doesn't exist, or updating a row if it matches. When simply updating one table based on the rows of another table, improve the performance and scalability with basic INSERT, UPDATE, and DELETE statements. For example:

This was obtained from the official MERGE Documentation

@thienvc
Copy link
Contributor Author

thienvc commented Nov 24, 2021

Yes, a PR for that would be welcome. You'd need to introduce a new SQL file, 09.10.03.SqlDataProvider with the code to update that stored procedure.

Also, I've updated this PR to target the develop branch (the master branch is only updated when new versions are released). Can you rebase your changes on develop? It may be easier to start a new branch from develop just for this PR and re-submit from that branch.

Thanks!

I'm not very good with Github but let me try

@thienvc
Copy link
Contributor Author

thienvc commented Nov 24, 2021

I suggest using a SQL merge statement instead for better performance MERGE INTO {databaseOwner}[{objectQualifier}outputCache] T USING (SELECT @itemid as ItemID, @Cachekey as CacheKey, ...) S on T.cacheKey = S.CacheKey WHEN NOT EXIST THEN Insert (ItemID, CacheKey, ...) VALUES S.ItemID, S.CacheKey, ...)

If adding the SQL fix I believe that the structure outlined by @thienvc is appropriate, per the following guidance from Microsoft.

Performance Tip: The conditional behavior described for the MERGE statement works best when the two tables have a complex mixture of matching characteristics. For example, inserting a row if it doesn't exist, or updating a row if it matches. When simply updating one table based on the rows of another table, improve the performance and scalability with basic INSERT, UPDATE, and DELETE statements. For example:

This was obtained from the official MERGE Documentation

Thanks @sleupold @mitchelsellers I haven't used Merge, so not sure about performance, someone who has tested Profiler and has more experience can give me some advice

@bdukes
Copy link
Contributor

bdukes commented Nov 29, 2021

@mitchelsellers I think that's talking about syncing between two tables, where the source of the data being inserted into the table is another query. I don't think that applies here. The first example in that documentation matches what we're trying to do here. It also reduces the possibility for a concurrency race to use MERGE instead of multiple statements.

thienvc added a commit to thienvc/Dnn.Platform that referenced this pull request Dec 6, 2021
@mitchelsellers mitchelsellers merged commit 5ae6981 into dnnsoftware:develop Jan 18, 2022
@valadas valadas modified the milestones: 9.10.3, 9.11.0 Sep 28, 2022
@thienvc
Copy link
Contributor Author

thienvc commented Mar 16, 2024

Oh, after 2 years it seems this error is back

@valadas
Copy link
Contributor

valadas commented Mar 16, 2024

@thienvc I would recommend creating a new issue with steps to reproduce referencing this PR.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Page OutputCache wrong expire date format
5 participants