When dealing with sequence data it is usual to have sequences with different sizes. One answer for your problem might be to using padding in your events, in this way you keep a fixed number of events for all your data.
It happens in the same way with NLP applications, let's set number of events to be five.
So you have the following two rows in your data set:
UserID | time | eventType | eventData
1 08:00:00 A X
1 08:01:00 A X
1 08:02:00 B X
1 08:03:00 C Y
1 08:03:00 A Z
1 08:00:00 A X
2 07:00:00 A Z
2 07:01:00 B X
So, you have for userId = 1 six events and for userId = 2 two events. Using paddings = 5, you will add 'Null'/Zero data for user 2 and you will truncate one event for user 1. Usually, you keep the last ones, so your data will become:
UserID | time | eventType | eventData
1 08:01:00 A X
1 08:02:00 B X
1 08:03:00 C Y
1 08:03:00 A Z
1 08:00:00 A X
2 07:00:00 Null Null
2 07:00:00 Null Null
2 07:00:00 Null Null
2 07:00:00 A Z
2 07:01:00 B X
But what about the null values? You can use GradientBoosting algorithms that deals with null values by default. Or a missing imputation stretegy such as the most common value or a new class indicating null value.
Then, to finish, you can transform your data to have each user a row in your dataset:

Notice that your 'window' size is a hyperparameter and it is a good practice to define it via cross-validation.
I hope it helps.