Closed (fixed)
Project:
Drupal core
Version:
8.0.x-dev
Component:
user system
Priority:
Major
Category:
Task
Assigned:
Issue tags:
Reporter:
Created:
28 Mar 2014 at 16:47 UTC
Updated:
29 Jul 2014 at 23:30 UTC
Jump to comment: Most recent, Most recent file
Comments
Comment #1
znerol commentedComment #2
sunNativeSessionStoragecomes with tons of own special behavior and presents a significant change to our session handling.As discussed in IRC, I'd really really prefer to limit this issue to a second baby step:
Just simply objectify the remainder of session.inc + get rid of session.inc.
That's a large enough task of its own. Similarly hairy as #2205295: Objectify session handler, because we need to resolve some Simpletest problems. I'd like to avoid any additional cause for potential problems and change in behavior within this step.
Comment #3
ParisLiakos commentedi agree. we should bring the symfony code in over at #1858196: [meta] Leverage Symfony Session components. Then we can have a clearer picture on whats going wrong with testbot and less places to debug.
Lets not remove session.inc here though. Just keep the procedural wrappers and just deprecate them?
Comment #4
sun@ParisLiakos: To my knowledge, there are only a handful of calls to those functions throughout core, so converting them should be a no-brainer. That said, we can happily defer that decision to "later" in this issue + keep the procedural wrappers for now — let's focus on the real meat first :-)
Comment #5
znerol commentedRemoved the base class for the moment. Tried some tests and at least session and authorization is passing locally. However, at the end of the batch process I'm logged out (when testing with the UI). @sun, perhaps you have a clue whats going on. Logout seems to happen during batch processing.
Regarding
NativeSessionStorage, please take a closer look at the source. The class is really not that big and half of it is just setters and getters. Also I'd like to point out that we need something like the AttributesBag in order to decouple session management from user authentication. IMHO the Symfony session implementation is quite lean and I do not see too much things which may get in the way (except for simpletest).Comment #6
znerol commentedComment #9
ParisLiakos commentedImo we should:
sessionserviceCookieauthentication provider instead of requiring session.inc, have thesessionservice injected.$this->session->init()instead ofdrupal_session_initialize().$this->session->save()instead ofdrupal_session_commit()And in general
Stop loading session.inc
Move session.inc's public functions to public methods in
sessionserviceThis way, we move the session handling to DIC -> win!
Comment #10
sunI don't get why both drupal_session_initialize() + _start() are calling ::initialize()...?
The former should not call ::initialize(), 'cos that's part of the DI construction already (very debatable).
And the latter should call ::start(), because we're *explicitly* asked to start a session, not just initialize it.
Due to the DI service declaration, checking whether a session was started means that a session WILL BE started - no good ;)
Comment #11
znerol commented1. Fixed
2. The only invocation in head is in the cookie-provider, the problem does not exist there. I left the function in because it is in the symfony interface.
Comment #12
znerol commentedComment #13
ParisLiakos commentedComment #15
sunSomehow, I can't see why this shouldn't work as-is, without any further adjustments...?
For 100% completeness, I'm additionally attaching a diff between 8.x session.inc + Storage.php, generated via:
Comment #17
sunFixed invalid PHP syntax.
Comment #18
ParisLiakos commentedwe should name it Session too:)
we should inject the request
Can we name this migrate() instead to emulate Symfony\Component\HttpFoundation\Session\SessionInterface::migrate()? Makes transition easier
Comment #20
sunFixed invalid method name. Sorry.
Comment #21
sunAddressing 1+3 of #18.
re 2) I can only assume that constructor-injecting the request will open a huge can of worms... the usual lack-of-synchronization drama, if you will.
Comment #23
sunSorry, I missed to rename the actual class in #21... Attached patch adjusts that patch in-place.
Comment #24
sunConstructor-inject the request into Session service.
I'm fairly sure this will break, so we probably want to skip that step here...
Comment #28
ParisLiakos commentedso now the $set is ignored if something passes it :)
we need to have the functionality in the Session class changing the started property
Comment #29
jibranThis is a service we need an interface.
Comment #30
skipyT commentedfixed the failed tests. now I will do the remaining tasks:
- create an interface for the Session class
- remove session.inc
- class the service from the auth provider and the other files (this will be a little bit harder)
- pushing a new patch in about one hour
Comment #31
skipyT commentedComment #32
znerol commentedI was able to reproduce the test failures in #24. Let's try to track the number of calls to
disableandenableand only allow saving the session whenstatic::$disableLevel == 0.Comment #33
skipyT commentedremoved session.inc
rewrote every file to use the session service
TODO:
- rename the session service
- create the interface
Comment #34
znerol commentedI am very unhappy with the renaming from #15. The
sessionservice in symfony is something completely different than the thing we are building here. When we keep the name that way, this will be utterly confusing for everyone. I suggest setting up our services in a similar way like others do. For the reference, this is the session service configuration of the framework bundle: session.xml.Therefore I suggest the following:
[...]\HttpFoundation\Session\Session(the symfony session, implementsSessionInterface)Drupal\Core\Session\DefaultStorageor alternativelySessionManager(the stuff from this patch, implements[...]\HttpFoundation\Session\Storage\SessionStorageInterface)Drupal\Core\Session\SessionHandler(the database/mongodb/whatever backend, see also #2228393: Decouple session from cookie based user authentication implements\SessionHandlerInterfaceand in an ideal world alsoDrupal\Core\Session\SslAwarySessionHandlerInterface)Comment #35
skipyT commentedOk, I agree with this renaming strategy. And I think now, when we'll add the interfaces we should already rename those classes in the proper way.
Comment #38
ParisLiakos commentedi am just reuploading the patch in #30 to see if its green.
i am not gonna fight more over naming
Comment #39
sunOn it.
Comment #40
sunAttached patch is based on @skipyT's #30 + #33.
(btw, it was a bit hard to figure out what exactly happened around ~#30 and which interdiffs to apply to my local branch...)
For completeness, I'm also attaching a new diff between 8.x session.inc vs. SessionManager again.
@jibran:
This patch will not introduce an interface for
SessionManager, because this is just the second baby step, and subsequent follow-up issues will significantly change the session subsystem. Therefore, it does not make sense to introduce an interface (API), because the public API is going to be changed.Comment #42
znerol commentedThis feels somewhat strange. Can we do it the other way around? I.e. inject the
SessionHandlerinto theSessionManagerand let the latter forward enable/disable?Comment #43
sunre: #42:
Let's simply stick to the current reality. It doesn't help us to "hide" or ignore dependencies in this conversion.
Much rather the opposite: By injecting them properly, the result is a very clear big picture of how the current classes are inter-operating with each other.
In turn, that allows us to make very simple + clear statements in follow-up issues à la "This class should not get that class injected, because ..."
Comment #44
skipyT commentedthis look good for me, if we get green on the last patch we can ask for RTBC. I think this will be enough for this step.
Comment #45
ParisLiakos commentedi agree with #44
BUT
If we are removing session.inc and we dont add an interface, what do we write in the change notice? (I dont think we will ever get an api change approval this way)
Thats why we should add an interface. The public facing methods will all remain anyway.
So lets have a
Drupal\Core\Session\SessionInterfacewith the following methods:In the future this interface will extend from the symfony one, but there will be no api change there, because those methods will remain.
Comment #46
znerol commentedI'm okay with adding an interface for those methods not covered by
[...]\HttpFoundation\Session\Storage\SessionStorageInterface. Also in addition express the intention to migrate to the aforementioned interface by rebasing theSessionManagerto[...]\HttpFoundation\Session\Storage\NativeSessionStorage.Comment #47
sunAdded SessionManagerInterface.
Not going to express any intentions in code, because there is still way too much discussion and disagreement on those fronts ;-) — The ultimate intentions will be figured out in issues, not code comments.
Comment #48
ParisLiakos commentedComment #49
sunAfter lots of back and forth in IRC, this
SessionManagerclass is actually the equivalent of the concept that Symfony calls "Session Storage" (yet another ugly misnomer!):https://github.com/symfony/symfony/blob/master/src/Symfony/Component/Htt...
The
migrate()method only exists on theSessionclass in Symfony, which is a concept that does not exist in Drupal core yet:https://github.com/symfony/symfony/blob/master/src/Symfony/Component/Htt...
Focus is really hard on "yet" — the ultimate goal of the parent issue is to introduce and use that Symfony
Sessionclass (as-is) in Drupal core. But this issue here is just a baby step towards that goal - we're not there yet. But still,SessionManager!=Session.Therefore:
Reverted rename of SessionManager::regenerate().
Comment #50
sunUpdated + rewrote issue summary to fully reflect the changes of this baby step.
Will create a draft change notice in a moment.
Comment #51
sunDraft change notice: https://drupal.org/node/2228871
Comment #52
sunEveryone involved in here thinks that this is RTBC, but no one feels bold enough to promote it. — Anyone else out there?
FWIW, the last cross-branch-file diff from #40 is still applicable — only the
migrate()method name was reverted back toregenerate().This should help reviewers to confirm that the actual meat of the former procedural session.inc functions are not actually changed here.
Comment #53
cosmicdreams commentedlooks good to me. I had hoped that we could have removed more usages of global $user in this effort but agree that could happen in a next step.
The focus of this issue largely what we had attempted to do in #1858196: [meta] Leverage Symfony Session components. Great work!
Comment #54
znerol commentedWe only possibly can start to remove references to the global
$userwhen we have all session components in place.Comment #55
znerol commentedFollowup: #2229145: Register symfony session components in the DIC and inject the session service into the request object
Comment #56
dawehnerWe do have an interface so we can also typehint that.
If we explicit need the master request shouldn't we then use the request stack and ask for the master request? What ensures that the request here is the master one.
I don't see why this properties should be static ... everything interacts with actual instances of the object anyway.
Will we have a better place for drupal_is_cli() in the future?
Comment #57
klausiWe should also look at SessionTestSubscriber (used in SessionTest.php) where we have to call the ugly "\Drupal::currentUser()->getAccount();" just to initialize the session. That should probably be replaced with some start() call to the session manager service.
Comment #58
znerol commentedSimpletest woes. Probably needs better documentation.
I also discovered that it is actually a requirement that we implement
SessionStorageInterfacein order to be able to use the new session manager together with the SymfonySessionobject. Therefore I'd like to explore now whether it would be revisit the original proposal and makeSessionManagera subclass ofNativeSessionStorage. With the interface being almost identical, i expect changes to be minimal.Comment #59
sunThanks for your reviews!
Please note that this issue intentionally is a second baby step only. We are purposively NOT changing any implementations and/or calling code. The existing functionality is converted as-is into a service only.
re: #56.3: Both
$enabledand$startedwere static variables previously, so this is taken over literally from HEAD. It is required for tests to pass, in particular because web tests as well as the installer are futzing with these global/static session state properties. The code is moved as-is. Figuring out a more appropriate home for these properties and methods is out of scope of this issue. That will be part of the later steps in the transition to Symfony's session handling.re: #56.4:
drupal_is_cli()is only inlined into theSessionManagerclass to remove an unnecessary dependency on procedural code. This method is not supposed to be a replacement fordrupal_is_cli()(is is protected to begin with).re: #57: If that is required in HEAD, then it is also required with this patch, because the implementation is not changed at all. This patch converts the remainder of session.inc into a service/class.
As transparently demonstrated with the cross-branch-file diff session.manage.txt in #40, the class contains the exact same code. No functional changes.
Our one and only intention here are the steps outlined in the issue summary. We want to avoid scope-creep at all costs, because that is what caused #1858196: [meta] Leverage Symfony Session components to get stuck forever.
The vast majority of this code will most likely be relocated and significantly changed, once we have the baseline to get back to work on the conversion to Symfony's session handling.
Comment #60
sun2) is for consistency; I hope that it doesn't break anything.
Comment #62
dawehnerFor now using the current request is exactly what core does. We should think about using the master request explicit in a follow up.
Comment #63
sunCreated #2229223: RequestStack is not persisted across kernel rebuilds
Comment #64
znerol commentedI still think that it would be very worthwile to rebase
SessionManagerontoNativeSessionStorage. The changes really are trivial. Attached is not a full patch but an interdiff of the proposed changes (applies to #59). @sun pretty please can we get them in here?Comment #65
znerol commentedIgnore #64. Regrettably this is still flawed, definitely needs more thought.
Comment #66
sun60: session.manage.60.patch queued for re-testing.
Comment #67
sunComment #69
sunMerged 8.x.
Comment #71
sunAdded CLI check to SessionManager::initialize() to account for Drush.
Comment #73
sunD'oh. It certainly helps to comply with the interface ;-)
Comment #75
sunThe test failures all happen to be related to Locale. Debugging those yields the following backtrace:
→
file_get_stream_wrappers()is invoked during bootstrap, beforeHttpKernel::handle()adds the current request to the request stack.In #2229223: RequestStack is not persisted across kernel rebuilds, I sorta intentionally skipped
drupal_handle_request()+_drupal_boostrap_kernel(), because I (wrongly) assumed that this code path would not be possible...→ Fixed current request is not available in request stack before HttpKernel::handle().
This effectively duplicates the master request in the request stack, but I do not see a way to work around that without significantly changing how Drupal is bootstrapped.
Comment #77
znerol commentedInstead of injecting
request/request_stackinto the constructor ofSessionManager, how about adding a$requestparameter to theinitializemethod?Comment #78
sunFixed mock Request in DUTB is not added to request stack.
Comment #80
sunOh, sorry. Last patch was bogus. :-/
Comment #81
sunBack green again. :-)
For completeness, I'm attaching a final diff between session.inc and SessionManager, generated via:
Comment #82
cosmicdreams commented@znerol shifting to setting injection instead of constructor injection doesn't buy us much.
The patch is green now so Yay! This is a solid step forward
Comment #83
znerol commentedNo injection at all, just pass in the request to
initializefrom the caller function (which would have been possible and would have solved the problem). But certainly I'm happy that this turned green again without that additional change.Comment #85
sunMerged 8.x. Just a merge conflict in DUTB due to a changed comment.
Comment #86
cosmicdreams commented85: session.manage.85.patch queued for re-testing.
Comment #87
sun@cosmicdreams: RTBC patches are automatically re-tested once per day now.
Comment #88
sunMoving forward here would allow us to validate some testing framework related changes in the kernelize-bootstrap patch.
Comment #89
cosmicdreams commented@sun Oh good news. No more manual retests.
I'm seeing a lot of issues modify their titles to include the number of issues that are postponed by parent issues. It might make sense to round up all the session related issues that relate to this and see if any need to be postponed until this issue gets in. I'm specifically thinking of how #961508: Dual http/https session cookies interfere with drupal_valid_token() will have a significant reroll because of this issue. There are likely others.
Comment #90
webchickThis one's a bit over my head, and catch has a busy week, so tossing over to Alex.
Also this "feels" major-ish, since the related issue is as well, although I could be wrong.
Comment #91
cosmicdreams commentedWhile it seems major, it's not doing anything different than it used to. We're just objectifying here.
Comment #92
alexpottLooking at the code in DrupalKernal I just can not see how a persisted service can ever actually be swapped out once the container is compiled. If a module swaps the session_manager then the persist logic will copy the old one back over the top and then the container will be dumped. The only way I can see would be to manually delete the container once the module that alters the session manager is installed.
Can we add a test to show that I'm wrong?
Comment #93
sun@alexpott: I'm not sure how that is related to this issue?
The current persist functionality does not persist service definitions, it only persists instances of services.
Instantiated services are persisted until
DrupalKernelis shut down (which resets the entire container to null).Therefore, if a (new) module swaps out a persisted service, then the new service definition will kick in as soon as
DrupalKernelis shut down and rebooted from scratch (typically happening on a new request, but also possible through a manualshutdown()→boot()sequence).Especially because
SessionManagerregisters theSessionHandlerto PHP core, that is a required behavior here, since swapping out and registering a new session handler to PHP core mid-request is not something that can reasonably work (without a facility to migrate an existing session from one session handler to a new session handler).In addition, swapping out
session.incmid-request is and was not possible before in HEAD either, because procedural functions can only be loaded once.Therefore, this patch only converts the existing functionality and behavior as-is. I know you have reservations regarding persisted services (though possibly also a misunderstanding of how persisted services work?), but that is status quo and the only existing mechanism in HEAD. — We can discuss to replace that mechanism with a better one and/or possible ways to eliminate
ModuleHandler::updateModules(), but that's a very complex separate discussion to have and it's not clear why that should hold up this issue...?Comment #94
alexpottSo @sun is correct - I wrote a module to swap out the container and the dumped version contains the replaced class...
Setting back to rtbc as I was responsible for derailing.
Comment #95
alexpottCommitted 12abe62 and pushed to 8.x. Thanks!
Comment #97
sunThanks! :-)
Comment #98
znerol commentedFollow-up: #2238087: Rebase SessionManager onto Symfony NativeSessionStorage