Skip to content

Flush running on main thread and may take a long time #257

Closed
@cprince-foreflight

Description

@cprince-foreflight

Describe the bug
We recently have switched over to using your Segment Swift-based library (from your Objective-C library).
We have code in our app that checks whether the main thread is blocked for relatively long periods of time.
We have noticed that:
(a) flush operations take place on the main thread, and
(b) those flush operations can take significant amounts of time. E.g., > 3 seconds.

To Reproduce
Steps to reproduce the behavior:

  1. Turn off all networking on device. E.g., airplane mode.
  2. Log numerous Segment events.
  3. Turn networking back on on device.
  4. Observe that flush takes place on main thread and that main thread is blocked for a relatively long period of time.

Expected behavior
Given that the flush can take a relatively long period of time (roughly proportional to the number of events pending to be sent), I expect the flush to not take place on the main thread-- which will lock up the UI if the app is in the foreground.

Screenshots
N/A

Platform (please complete the following information):

  • Library Version in use: 1.4.7
  • Platform being tested: iOS

Additional context
Our app serves pilots flying aircraft and in this context the devices typically do not have a networking connection, but Segment events are logged during flights. When the pilot lands, and again has networking, Segment events get uploaded.

Questions

  1. We are planning to work around this issue by using custom flush policies which directly call the flush operation (e.g., as in IntervalBasedFlushPolicy), but which wrap the flush call in use of a background thread. Do you see any problematic consequences of this strategy in terms of the broader Segment library and system? So far in initial testing it works with no problem.

  2. Would you be open to a PR to change this? The simplest approach seems to me to wrap the bulk of the flush code in a block executing on a background thread. Example:

    public func flush() {
        // only flush if we're enabled.
        guard enabled == true else { return }
        
        DispatchQueue.global(qos: .background).async {
            apply { plugin in
                if let p = plugin as? EventPlugin {
                    p.flush()
                }
            }
        }
    }

Metadata

Metadata

Assignees

Labels

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions